@evotecit/canopyx 0.1.2 → 0.2.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-calendar-edit.js +113 -0
- package/CanopyX.Html/Assets/canopyx-calendar-ics.js +87 -0
- package/CanopyX.Html/Assets/canopyx-calendar-recurrence.js +36 -0
- package/CanopyX.Html/Assets/canopyx-calendar.css +279 -0
- package/CanopyX.Html/Assets/canopyx-calendar.js +307 -0
- package/CanopyX.Html/Assets/canopyx-cell-range.css +38 -0
- package/CanopyX.Html/Assets/canopyx-cell-range.js +141 -0
- package/CanopyX.Html/Assets/canopyx-column-groups.css +18 -0
- package/CanopyX.Html/Assets/canopyx-column-groups.js +51 -0
- package/CanopyX.Html/Assets/canopyx-data.js +14 -0
- package/CanopyX.Html/Assets/canopyx-detail-rows.css +18 -0
- package/CanopyX.Html/Assets/canopyx-detail-rows.js +51 -0
- package/CanopyX.Html/Assets/canopyx-editing.css +44 -0
- package/CanopyX.Html/Assets/canopyx-editing.js +134 -0
- package/CanopyX.Html/Assets/canopyx-enhance.js +126 -0
- package/CanopyX.Html/Assets/canopyx-export.js +18 -0
- package/CanopyX.Html/Assets/canopyx-facets.css +86 -0
- package/CanopyX.Html/Assets/canopyx-facets.js +65 -0
- package/CanopyX.Html/Assets/canopyx-filter-editor.css +15 -18
- package/CanopyX.Html/Assets/canopyx-filter-editor.js +23 -17
- package/CanopyX.Html/Assets/canopyx-format-editor.css +77 -0
- package/CanopyX.Html/Assets/canopyx-format-editor.js +30 -0
- package/CanopyX.Html/Assets/canopyx-formatting.css +40 -0
- package/CanopyX.Html/Assets/canopyx-formatting.js +101 -0
- package/CanopyX.Html/Assets/canopyx-grid-module.mjs +352 -246
- package/CanopyX.Html/Assets/canopyx-grid.css +139 -117
- package/CanopyX.Html/Assets/canopyx-grid.js +352 -246
- package/CanopyX.Html/Assets/canopyx-grouping.css +39 -0
- package/CanopyX.Html/Assets/canopyx-grouping.js +85 -0
- package/CanopyX.Html/Assets/canopyx-highlight.css +34 -0
- package/CanopyX.Html/Assets/canopyx-highlight.js +80 -0
- package/CanopyX.Html/Assets/canopyx-history.js +13 -0
- package/CanopyX.Html/Assets/canopyx-interactive.css +18 -6
- package/CanopyX.Html/Assets/canopyx-interactive.js +179 -100
- package/CanopyX.Html/Assets/canopyx-labels-de.js +304 -0
- package/CanopyX.Html/Assets/canopyx-labels-es.js +304 -0
- package/CanopyX.Html/Assets/canopyx-labels-fr.js +529 -0
- package/CanopyX.Html/Assets/canopyx-labels-it.js +529 -0
- package/CanopyX.Html/Assets/canopyx-labels-pl.js +304 -0
- package/CanopyX.Html/Assets/canopyx-layouts.css +48 -0
- package/CanopyX.Html/Assets/canopyx-layouts.js +39 -0
- package/CanopyX.Html/Assets/canopyx-link.css +19 -0
- package/CanopyX.Html/Assets/canopyx-link.js +38 -0
- package/CanopyX.Html/Assets/canopyx-links.js +14 -0
- package/CanopyX.Html/Assets/canopyx-live.css +24 -0
- package/CanopyX.Html/Assets/canopyx-live.js +88 -0
- package/CanopyX.Html/Assets/canopyx-module.mjs +180 -100
- package/CanopyX.Html/Assets/canopyx-pager.css +10 -0
- package/CanopyX.Html/Assets/canopyx-pager.js +14 -0
- package/CanopyX.Html/Assets/canopyx-record-panel.css +111 -0
- package/CanopyX.Html/Assets/canopyx-record-panel.js +178 -0
- package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +406 -342
- package/CanopyX.Html/Assets/canopyx-reporting.css +140 -135
- package/CanopyX.Html/Assets/canopyx-reporting.js +406 -342
- package/CanopyX.Html/Assets/canopyx-search.js +32 -0
- package/CanopyX.Html/Assets/canopyx-timeline.css +80 -0
- package/CanopyX.Html/Assets/canopyx-timeline.js +88 -0
- package/CanopyX.Html/Assets/canopyx-tree-tools.css +103 -0
- package/CanopyX.Html/Assets/canopyx-tree-tools.js +92 -0
- package/CanopyX.Html/Assets/canopyx.css +17 -5
- package/CanopyX.Html/Assets/canopyx.js +175 -96
- package/JavaScript/calendar.d.ts +362 -0
- package/JavaScript/cell-ranges.d.ts +76 -0
- package/JavaScript/column-groups.d.ts +32 -0
- package/JavaScript/editing.d.ts +257 -0
- package/JavaScript/enhance.d.ts +202 -0
- package/JavaScript/facets.d.ts +58 -0
- package/JavaScript/formatting.d.ts +88 -0
- package/JavaScript/grid.d.ts +409 -56
- package/JavaScript/hosts.d.ts +177 -2
- package/JavaScript/index.d.ts +53 -4
- package/JavaScript/live.d.ts +115 -0
- package/JavaScript/locales/de.mjs +304 -0
- package/JavaScript/locales/es.mjs +304 -0
- package/JavaScript/locales/fr.d.ts +6 -0
- package/JavaScript/locales/fr.mjs +527 -0
- package/JavaScript/locales/it.d.ts +6 -0
- package/JavaScript/locales/it.mjs +527 -0
- package/JavaScript/locales/pl.mjs +304 -0
- package/JavaScript/plugins.d.ts +113 -0
- package/JavaScript/protocol.d.ts +139 -6
- package/JavaScript/records.d.ts +136 -0
- package/README.md +61 -9
- package/README.nuget.md +1 -1
- package/package.json +99 -3
|
@@ -0,0 +1,257 @@
|
|
|
1
|
+
// Editing of flat grids (docs/editing.md): typed editors, validation, the change set, row and batch commit, undo and redo.
|
|
2
|
+
import type { CellValue, Cell, TimeZone } from "./protocol.js";
|
|
3
|
+
import type { GridRow, GridQuery, AcceptedGridQuery } from "./grid.js";
|
|
4
|
+
|
|
5
|
+
/** A built-in editor type, or the name of an editor a plugin or the host registers. */
|
|
6
|
+
export type GridEditorType = "text" | "number" | "date" | "datetime" | "time" | "select" | "toggle" | "lookup" | (string & {});
|
|
7
|
+
|
|
8
|
+
/** A select choice or a fixed lookup suggestion: a raw value, or a value with the label readers see. */
|
|
9
|
+
export type GridEditorOption = string | number | boolean | { value: string | number | boolean; label?: string };
|
|
10
|
+
|
|
11
|
+
/** The editor of an editable column; a name alone is shorthand for { type }. */
|
|
12
|
+
export type GridEditorDefinition = GridEditorType | {
|
|
13
|
+
type: GridEditorType;
|
|
14
|
+
/** Number editors: the smallest value, also the start of step. */
|
|
15
|
+
min?: number;
|
|
16
|
+
/** Number editors: the largest value. */
|
|
17
|
+
max?: number;
|
|
18
|
+
/** Number editors: Up and Down move by it; values keep its multiple. */
|
|
19
|
+
step?: number;
|
|
20
|
+
placeholder?: string;
|
|
21
|
+
/** Select choices, or a lookup's fixed suggestions (at most 1000). */
|
|
22
|
+
options?: readonly GridEditorOption[];
|
|
23
|
+
/** Lookups: the column whose values it suggests through the data source (default the edited column), how many (1..50, default 20) and after how many characters (0..16, default 1). */
|
|
24
|
+
lookup?: { column?: string; limit?: number; minLength?: number };
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/** Checks an edited value must pass before its row commits; the messages are the gridEdit… labels unless message replaces them. */
|
|
28
|
+
export interface GridValidation {
|
|
29
|
+
required?: boolean;
|
|
30
|
+
/** A number, or an ISO 8601 moment with its time zone for date-and-time columns. */
|
|
31
|
+
min?: number | string;
|
|
32
|
+
max?: number | string;
|
|
33
|
+
minLength?: number;
|
|
34
|
+
maxLength?: number;
|
|
35
|
+
/** A regular expression the whole text must match. */
|
|
36
|
+
pattern?: string;
|
|
37
|
+
message?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/** The view document's editing settings; the editing option overrides them. */
|
|
41
|
+
export interface GridEditingSettings {
|
|
42
|
+
/** The whole grid is read-only until setReadOnly(false). */
|
|
43
|
+
readOnly?: boolean;
|
|
44
|
+
/** One cell at a time (default), or every editable cell of a row. */
|
|
45
|
+
mode?: "cell" | "row";
|
|
46
|
+
/** When the record drawer becomes an edit form (default "phone"). */
|
|
47
|
+
drawer?: "phone" | "always" | "never";
|
|
48
|
+
/** The toolbar shows unsaved changes with Undo, Redo, Discard and Save (default true). */
|
|
49
|
+
editBar?: boolean;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** What an editor's create function receives. Frozen. */
|
|
53
|
+
export interface CanopyEditorContext {
|
|
54
|
+
/** A unique id prefix for elements the editor creates. */
|
|
55
|
+
readonly id: string;
|
|
56
|
+
/** The cell's raw value when editing starts. */
|
|
57
|
+
readonly value: CellValue;
|
|
58
|
+
/** The cell's display text. */
|
|
59
|
+
readonly text: string;
|
|
60
|
+
/** A frozen copy of the record. */
|
|
61
|
+
readonly row: Readonly<GridRow>;
|
|
62
|
+
readonly column: Readonly<{ id: string; title: string; kind: "text" | "number" | "datetime" }>;
|
|
63
|
+
/** The column's editor definition, with its type. */
|
|
64
|
+
readonly editor: Readonly<Exclude<GridEditorDefinition, string>>;
|
|
65
|
+
readonly options: readonly Readonly<{ value: string | number | boolean; label: string }>[] | null;
|
|
66
|
+
readonly rules: Readonly<GridValidation & { step?: number }>;
|
|
67
|
+
readonly labels: Readonly<Record<string, string>>;
|
|
68
|
+
/** The page language, for parsing and formatting. */
|
|
69
|
+
readonly locale: string | undefined;
|
|
70
|
+
/** The grid's time zone: dates are shown and entered in it. */
|
|
71
|
+
readonly timeZone: TimeZone;
|
|
72
|
+
/** Where the editor is: a cell, a row in full-row mode, or the drawer's edit form. */
|
|
73
|
+
readonly mode: "cell" | "row" | "form";
|
|
74
|
+
/** The character the reader typed to start editing ("" for Backspace or Delete), when there is one. */
|
|
75
|
+
readonly initial: string | undefined;
|
|
76
|
+
/** Aborts when the editor closes. */
|
|
77
|
+
readonly signal: AbortSignal;
|
|
78
|
+
readonly lookupMinLength: number;
|
|
79
|
+
/** Applies the editor's value and closes it. */
|
|
80
|
+
commit(): void;
|
|
81
|
+
/** Closes the editor without applying. */
|
|
82
|
+
cancel(): void;
|
|
83
|
+
/** Searches the column's suggestions as a lookup does. */
|
|
84
|
+
lookup(search: string, signal: AbortSignal): Promise<readonly { value: string | number | boolean; label: string }[]>;
|
|
85
|
+
/** Remembers a chosen suggestion, so the cell shows its label. */
|
|
86
|
+
remember(option: { value: string | number | boolean; label: string }): void;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
/** An editor instance. getValue returns the raw cell value; error returns a message while the input is not a value yet. */
|
|
90
|
+
export interface CanopyEditorInstance {
|
|
91
|
+
/** What goes into the cell (or the form field). */
|
|
92
|
+
readonly element: HTMLElement;
|
|
93
|
+
/** The focusable control, when it is not element itself; it gets the accessible name and the invalid state. */
|
|
94
|
+
readonly control?: HTMLElement;
|
|
95
|
+
getValue(): CellValue;
|
|
96
|
+
focus?(): void;
|
|
97
|
+
error?(): string | null;
|
|
98
|
+
destroy?(): void;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** A typed cell editor a plugin (editors) or the host (editing.editors) registers under a name. */
|
|
102
|
+
export interface CanopyCellEditor {
|
|
103
|
+
create(context: CanopyEditorContext): CanopyEditorInstance;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** A row's change: the new values and the values the row started from; a new row (op "insert") has no original. */
|
|
107
|
+
export type GridChange = GridUpdateChange | GridInsertChange;
|
|
108
|
+
/** A change of a stored row. */
|
|
109
|
+
export interface GridUpdateChange extends GridChangeState {
|
|
110
|
+
readonly op?: "update";
|
|
111
|
+
readonly original: Readonly<Record<string, CellValue>>;
|
|
112
|
+
}
|
|
113
|
+
/** A new row from insertRow: every value, no original. */
|
|
114
|
+
export interface GridInsertChange extends GridChangeState {
|
|
115
|
+
readonly op: "insert";
|
|
116
|
+
}
|
|
117
|
+
/** What every change carries. */
|
|
118
|
+
export interface GridChangeState {
|
|
119
|
+
readonly id: string;
|
|
120
|
+
readonly values: Readonly<Record<string, CellValue>>;
|
|
121
|
+
/** Messages by column of the failed checks. */
|
|
122
|
+
readonly errors?: Readonly<Record<string, string>>;
|
|
123
|
+
/** The row's own message: a row check or a failed save. */
|
|
124
|
+
readonly error?: string;
|
|
125
|
+
readonly status?: "saving" | "error" | "conflict";
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/** What a writer answers for one row of a gridCommit. */
|
|
129
|
+
export interface GridCommitRowResult {
|
|
130
|
+
status: "saved" | "error" | "conflict";
|
|
131
|
+
/** Saved rows: canonical cells that replace the shown ones. */
|
|
132
|
+
cells?: Record<string, Cell>;
|
|
133
|
+
/** A saved insert: the identity the writer stored the new row under (the client id new-<n> is replaced). */
|
|
134
|
+
newId?: string;
|
|
135
|
+
error?: string;
|
|
136
|
+
errors?: Record<string, string>;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** Changed rows a grid asks its writer to save (docs/data-protocol.md#editing-and-commit). */
|
|
140
|
+
export interface GridCommit {
|
|
141
|
+
readonly protocol: "canopyx/2";
|
|
142
|
+
readonly type: "gridCommit";
|
|
143
|
+
readonly view: string;
|
|
144
|
+
/** The dataset revision the grid read, or null. */
|
|
145
|
+
readonly revision: string | null;
|
|
146
|
+
/** Updates carry the original values; inserts (op "insert", a client id new-<n> or the host's) carry every value and no original. */
|
|
147
|
+
readonly rows: readonly ({ readonly op?: "update"; readonly id: string; readonly values: Readonly<Record<string, CellValue>>; readonly original: Readonly<Record<string, CellValue>> }
|
|
148
|
+
| { readonly op: "insert"; readonly id: string; readonly values: Readonly<Record<string, CellValue>> })[];
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
/** A writer's answer to gridCommit. A row it leaves out was not saved; revision is the dataset revision after the commit. */
|
|
152
|
+
export interface GridCommitResult {
|
|
153
|
+
protocol: "canopyx/2";
|
|
154
|
+
type: "gridCommitResult";
|
|
155
|
+
view: string;
|
|
156
|
+
revision?: string;
|
|
157
|
+
rows: (GridCommitRowResult & { id: string })[];
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
/** The result of one row of a commit. */
|
|
161
|
+
export interface GridRowCommitOutcome {
|
|
162
|
+
readonly id: string;
|
|
163
|
+
readonly ok: boolean;
|
|
164
|
+
readonly status: "saved" | "pending" | "unchanged" | "invalid" | "cancelled" | "error" | "conflict" | "superseded";
|
|
165
|
+
readonly error?: string | null;
|
|
166
|
+
readonly errors?: Readonly<Record<string, string>>;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/** What commitChanges resolves with. */
|
|
170
|
+
export interface GridCommitOutcome {
|
|
171
|
+
readonly ok: boolean;
|
|
172
|
+
readonly saved: number;
|
|
173
|
+
readonly failed: number;
|
|
174
|
+
readonly rows: readonly GridRowCommitOutcome[];
|
|
175
|
+
/** The revision the writer answered with; the grid keeps reading pages at the one it accepted until it reloads. */
|
|
176
|
+
readonly revision?: string;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** cellValueChanging (cancelable) and cellValueChanged. */
|
|
180
|
+
export interface GridCellValueChange {
|
|
181
|
+
readonly id: string;
|
|
182
|
+
readonly column: string;
|
|
183
|
+
readonly value: CellValue;
|
|
184
|
+
readonly previous: CellValue;
|
|
185
|
+
readonly row: Readonly<GridRow>;
|
|
186
|
+
/** paste and fill come from the cell range part (docs/cell-ranges.md): pasted cells and the fill handle go through editing. */
|
|
187
|
+
readonly source: "edit" | "form" | "api" | "undo" | "redo" | "revert" | "paste" | "fill" | "calendar" | "accept";
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/** canopyx:rowCommit and onRowCommit: a row whose edits are complete and valid (a new row: op "insert" and no original). */
|
|
191
|
+
export interface GridRowCommit {
|
|
192
|
+
readonly id: string;
|
|
193
|
+
readonly op?: "update" | "insert";
|
|
194
|
+
readonly values: Readonly<Record<string, CellValue>>;
|
|
195
|
+
readonly original?: Readonly<Record<string, CellValue>>;
|
|
196
|
+
readonly row: Readonly<GridRow>;
|
|
197
|
+
readonly revision: string | null;
|
|
198
|
+
/** Answers for the row from an event listener: a result, true for saved, or a promise of one. */
|
|
199
|
+
respondWith(result: GridCommitRowResult | true | PromiseLike<GridCommitRowResult | true>): void;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/** A lookup search the host answers itself. */
|
|
203
|
+
export interface GridLookupRequest {
|
|
204
|
+
readonly column: string;
|
|
205
|
+
readonly search: string;
|
|
206
|
+
readonly limit: number;
|
|
207
|
+
readonly row: Readonly<GridRow>;
|
|
208
|
+
readonly signal: AbortSignal;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/** The host's editing option. */
|
|
212
|
+
export interface GridEditingOptions<Q extends AcceptedGridQuery = GridQuery> extends GridEditingSettings {
|
|
213
|
+
/** Per-row read-only rule; runs synchronously for every cell it is asked about. */
|
|
214
|
+
isEditable?(row: Readonly<GridRow>, column: string): boolean;
|
|
215
|
+
/** Per-column checks: a message, null, or a promise of one. */
|
|
216
|
+
validators?: Readonly<Record<string, (value: CellValue, row: Readonly<GridRow>) => string | null | undefined | PromiseLike<string | null | undefined>>>;
|
|
217
|
+
/** A row check before it commits: a row message, messages by column, null, or a promise of them. */
|
|
218
|
+
validateRow?(row: Readonly<GridRow>, change: GridChange): string | Record<string, string> | null | undefined | PromiseLike<string | Record<string, string> | null | undefined>;
|
|
219
|
+
/** Lookup suggestions by column, in place of the editor's options and the data source. */
|
|
220
|
+
lookups?: Readonly<Record<string, (request: GridLookupRequest) => readonly GridEditorOption[] | PromiseLike<readonly GridEditorOption[]>>>;
|
|
221
|
+
/** The text edited cells of a column show, by column: the same formatter the host's source text comes from, so every cell of the column reads alike. Without one, edited cells use the column's default formatting (or a choice's label). */
|
|
222
|
+
formatters?: Readonly<Record<string, (value: Exclude<CellValue, null>, row: Readonly<GridRow>) => string>>;
|
|
223
|
+
/** Editors for this grid, beside the built-in ones and the plugins'. */
|
|
224
|
+
editors?: Readonly<Record<string, CanopyCellEditor>>;
|
|
225
|
+
/** The batch writer; wins over the source's commit. */
|
|
226
|
+
commit?(batch: GridCommit, options: { signal: AbortSignal }): GridCommitResult | PromiseLike<GridCommitResult>;
|
|
227
|
+
/** Undo steps kept (0..10000, default 100). */
|
|
228
|
+
undoLimit?: number;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/** The editing members of a flat grid's API. */
|
|
232
|
+
export interface GridEditingApi {
|
|
233
|
+
/** Opens the editor of a loaded record's cell (the first editable visible cell without column); false when it cannot. */
|
|
234
|
+
beginEdit(id: string, column?: string, options?: { initial?: string }): Promise<boolean>;
|
|
235
|
+
/** Applies the open editors; false while a value fails a check. */
|
|
236
|
+
endEdit(): Promise<boolean>;
|
|
237
|
+
cancelEdit(): void;
|
|
238
|
+
isEditing(): boolean;
|
|
239
|
+
/** A host's change with the same events, history and checks as an edit; read-only rules do not apply. */
|
|
240
|
+
setCellValue(id: string, column: string, value: CellValue): Promise<{ applied: boolean; valid: boolean; error?: string }>;
|
|
241
|
+
/** Adds a new record (id: new-<n>, or the host's, which starts with new- too) as an insert in the change set: validated, undoable, committed as op "insert". */
|
|
242
|
+
insertRow(input: { id?: string; cells: Readonly<Record<string, Cell>> }): Promise<{ id: string; applied: boolean; valid: boolean; errors?: Record<string, string> }>;
|
|
243
|
+
getChanges(): GridChange[];
|
|
244
|
+
hasChanges(): boolean;
|
|
245
|
+
/** Puts rows (all by default) back to their starting values, as one undoable step. */
|
|
246
|
+
revertChanges(ids?: readonly string[]): void;
|
|
247
|
+
validate(ids?: readonly string[]): Promise<{ valid: boolean; rows: { id: string; valid: boolean; errors: Record<string, string>; error?: string | null }[] }>;
|
|
248
|
+
/** Checks a row and raises rowCommit; resolves with what the handler answered. */
|
|
249
|
+
commitRow(id: string): Promise<GridRowCommitOutcome>;
|
|
250
|
+
/** Sends every valid changed row (or the ids) to the writer in one gridCommit. */
|
|
251
|
+
commitChanges(options?: { ids?: readonly string[]; signal?: AbortSignal }): Promise<GridCommitOutcome>;
|
|
252
|
+
undo(): boolean;
|
|
253
|
+
redo(): boolean;
|
|
254
|
+
canUndo(): boolean;
|
|
255
|
+
canRedo(): boolean;
|
|
256
|
+
setReadOnly(readOnly: boolean): void;
|
|
257
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// Progressive enhancement of an existing table and simple init from data or a URL (docs/enhance.md).
|
|
2
|
+
import type { CanopyLabels } from "./protocol.js";
|
|
3
|
+
import type { DataGrid, GridColumn, GridHostOptions, GridPageLengthChoice, GridPaging, GridQuery, GridState, GridView } from "./grid.js";
|
|
4
|
+
|
|
5
|
+
/** What a column render is called for: the text shown, the sort value, the search value, and the value whose type sets the column kind. */
|
|
6
|
+
export type GridRenderPurpose = "display" | "sort" | "filter" | "type";
|
|
7
|
+
|
|
8
|
+
/** Where a render call happens: the record's position in the data, the column's position, and the column id. */
|
|
9
|
+
export interface GridRenderMeta {
|
|
10
|
+
readonly row: number;
|
|
11
|
+
readonly column: number;
|
|
12
|
+
readonly id: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** A column render: receives the column's field value, the purpose, the whole record and the position. */
|
|
16
|
+
export type GridRenderFunction<R = any> = (data: any, purpose: GridRenderPurpose, record: R, meta: GridRenderMeta) => unknown;
|
|
17
|
+
|
|
18
|
+
/** A render function, or per purpose a function or a field path of the record; "_" is the fallback for purposes not named. */
|
|
19
|
+
export type GridRender<R = any> = GridRenderFunction<R> | {
|
|
20
|
+
readonly display?: GridRenderFunction<R> | string;
|
|
21
|
+
readonly sort?: GridRenderFunction<R> | string;
|
|
22
|
+
readonly filter?: GridRenderFunction<R> | string;
|
|
23
|
+
readonly type?: GridRenderFunction<R> | string;
|
|
24
|
+
readonly _?: GridRenderFunction<R> | string;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* A column of CanopyX.enhance or CanopyX.grid: the grid column fields, plus where its values come from and how they read.
|
|
29
|
+
* For a table, the options at a header cell's index merge over that cell's data-* attributes.
|
|
30
|
+
*/
|
|
31
|
+
export interface GridColumnOptions<R = any> extends Partial<Omit<GridColumn, "id" | "title" | "kind" | "hidden">> {
|
|
32
|
+
/** The column id; defaults to the field name, or c0, c1, ... for positions. */
|
|
33
|
+
id?: string;
|
|
34
|
+
/** The header text; defaults to the table header or the field name. */
|
|
35
|
+
title?: string;
|
|
36
|
+
/** A field name, a dotted path ("owner.name") or an array position; defaults to the column's position. */
|
|
37
|
+
data?: string | number;
|
|
38
|
+
/** The value kind; auto (the default) reads it from the values: numbers, ISO dates, else text. date is datetime. */
|
|
39
|
+
type?: "text" | "number" | "datetime" | "date" | "auto";
|
|
40
|
+
/** The same as type, in the grid column's own name. */
|
|
41
|
+
kind?: "text" | "number" | "datetime";
|
|
42
|
+
/** Display, sort, search and type values computed from the record. */
|
|
43
|
+
render?: GridRender<R>;
|
|
44
|
+
/** False leaves the column out of the search box. Default true. */
|
|
45
|
+
searchable?: boolean;
|
|
46
|
+
/** False hides the column at first; readers can show it from the Columns menu. Default true. */
|
|
47
|
+
visible?: boolean;
|
|
48
|
+
hidden?: boolean;
|
|
49
|
+
/** Text an empty cell shows instead of the dash. */
|
|
50
|
+
defaultContent?: string;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** A URL source: read once for client-side processing, or asked for every query with serverSide. */
|
|
54
|
+
export interface GridUrlSource {
|
|
55
|
+
url: string;
|
|
56
|
+
/** Defaults to GET when there is no body, else POST. A server source posts the grid query as JSON. */
|
|
57
|
+
method?: string;
|
|
58
|
+
headers?: Readonly<Record<string, string>>;
|
|
59
|
+
/** Extra request data: query parameters for GET, JSON fields otherwise; a function receives the grid query in server mode. */
|
|
60
|
+
data?: Readonly<Record<string, unknown>> | ((query?: GridQuery) => Readonly<Record<string, unknown>> | undefined);
|
|
61
|
+
/** Where the records are in the answer: a property path ("" for the answer itself) or a function. Default: the answer, its data or its items. */
|
|
62
|
+
dataSrc?: string | ((answer: any) => any);
|
|
63
|
+
credentials?: RequestCredentials;
|
|
64
|
+
/** A function with the fetch signature, for authenticated clients or tests. */
|
|
65
|
+
fetch?: (input: string, init: RequestInit) => Promise<Response>;
|
|
66
|
+
/** Ask the server for every query (sort, search, filters, page) with the canopyx/2 grid query; it answers a grid page or { total, matched, items }. */
|
|
67
|
+
serverSide?: boolean;
|
|
68
|
+
/** A server source's value-list endpoint (canopyx/2 grid facet queries), used by the reporting runtime's value lists. */
|
|
69
|
+
facetUrl?: string;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** What stateSave stores: the grid's state, its named views and when it was saved. */
|
|
73
|
+
export interface GridStoredState {
|
|
74
|
+
time: number;
|
|
75
|
+
current: GridState;
|
|
76
|
+
views: { name: string; state: GridState }[];
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/** State saving between visits. */
|
|
80
|
+
export interface GridStateSaveOptions {
|
|
81
|
+
/** Default session. */
|
|
82
|
+
storage?: "session" | "local";
|
|
83
|
+
/** Seconds a stored state stays valid; 0 keeps it without a limit. Default 7200. */
|
|
84
|
+
duration?: number;
|
|
85
|
+
/** The storage key prefix; defaults to the page path. The grid id is added. */
|
|
86
|
+
key?: string;
|
|
87
|
+
/** Also keep the shareable part (sort, search, filters, page, page length) in the address. */
|
|
88
|
+
url?: false | "query" | "hash";
|
|
89
|
+
/** The address parameter; defaults to the grid id. */
|
|
90
|
+
parameter?: string;
|
|
91
|
+
/** Reads the state from the host's own store instead of browser storage. */
|
|
92
|
+
load?(event: { key: string; view: string }): GridStoredState | null | PromiseLike<GridStoredState | null>;
|
|
93
|
+
/** Writes the state to the host's own store instead of browser storage. */
|
|
94
|
+
save?(event: { key: string; view: string; state: GridStoredState }): void | PromiseLike<void>;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/** Short names for the texts people change most; every other text is a CanopyX label (labels). Unknown names are ignored. */
|
|
98
|
+
export interface GridTexts {
|
|
99
|
+
search?: string; info?: string; infoFiltered?: string; lengthMenu?: string; first?: string; previous?: string; next?: string; last?: string;
|
|
100
|
+
page?: string; all?: string; empty?: string; emptyReason?: string; noMatches?: string; loading?: string; loadFailed?: string; retry?: string;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/** The detail of draw, order, search, page and length: the accepted query and the paging it produced. */
|
|
104
|
+
export interface GridDrawEvent {
|
|
105
|
+
readonly query: GridQuery;
|
|
106
|
+
readonly paging: GridPaging;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/** The options of CanopyX.grid and CanopyX.enhance. Host options of createDataGrid (renderers, actions, plugins, toolbar, onQuery, ...) pass through. */
|
|
110
|
+
export interface GridInitOptions<R = any> extends Omit<GridHostOptions, "source" | "viewStore" | "labels"> {
|
|
111
|
+
/** The grid id; defaults to the element id. */
|
|
112
|
+
id?: string;
|
|
113
|
+
/** The accessible name; defaults to aria-label, the table caption or the title attribute. */
|
|
114
|
+
label?: string;
|
|
115
|
+
noun?: string;
|
|
116
|
+
/** Columns; for a table, options by header position. Without columns, the first record's fields (or positions) become columns. */
|
|
117
|
+
columns?: readonly (GridColumnOptions<R> | null | undefined)[];
|
|
118
|
+
/** Records as arrays or objects. */
|
|
119
|
+
data?: readonly R[];
|
|
120
|
+
/** A URL source; without declared column types it is read before the grid appears. */
|
|
121
|
+
url?: string | GridUrlSource;
|
|
122
|
+
/** Ask the URL for every query. The same as url.serverSide. */
|
|
123
|
+
serverSide?: boolean;
|
|
124
|
+
/** The record field (or a function) that gives each row its stable id; missing ids are generated from positions. */
|
|
125
|
+
rowId?: string | ((record: R, index: number) => string | number);
|
|
126
|
+
/** False scrolls all rows instead of paging. Default true. */
|
|
127
|
+
paging?: boolean;
|
|
128
|
+
/** Rows per page. Default 25. */
|
|
129
|
+
pageLength?: number;
|
|
130
|
+
/** Page-size choices. Default 10, 25, 50, 100 and All. */
|
|
131
|
+
pageLengths?: readonly GridPageLengthChoice[];
|
|
132
|
+
/** False hides the rows-per-page menu. */
|
|
133
|
+
lengthMenu?: boolean;
|
|
134
|
+
/** "sentence" (default), "range" (compact), or false for no result text. */
|
|
135
|
+
info?: boolean | "range" | "sentence";
|
|
136
|
+
/** Numbered page buttons: true for seven (default), a count from 5 to 15, or false. */
|
|
137
|
+
pageNumbers?: boolean | number;
|
|
138
|
+
/** The page number field; shown by default only without numbered pages. */
|
|
139
|
+
pageInput?: boolean;
|
|
140
|
+
/** False hides the first-page and last-page buttons. */
|
|
141
|
+
firstLast?: boolean;
|
|
142
|
+
/** False removes the search box. Default true. */
|
|
143
|
+
search?: boolean;
|
|
144
|
+
/** The initial search. */
|
|
145
|
+
searchText?: string;
|
|
146
|
+
searchMode?: "substring" | "words";
|
|
147
|
+
/** The initial sort: [[column position or id, "asc" | "desc"], ...] or [{ column, direction }, ...]. */
|
|
148
|
+
order?: readonly (readonly [number | string, ("asc" | "desc")?] | { column: number | string; direction?: "asc" | "desc" })[];
|
|
149
|
+
/** False makes every column unsortable unless a column says otherwise. Default true. */
|
|
150
|
+
sortable?: boolean;
|
|
151
|
+
selection?: "none" | "single" | "multiple";
|
|
152
|
+
stateSave?: boolean | GridStateSaveOptions;
|
|
153
|
+
texts?: GridTexts;
|
|
154
|
+
labels?: Partial<CanopyLabels>;
|
|
155
|
+
/** Keep the markup of table cells (links, badges) in the grid's cells. Default true. */
|
|
156
|
+
markup?: boolean;
|
|
157
|
+
/** False drops the table footer strip. Default: the table footer shows below the rows. */
|
|
158
|
+
footer?: boolean;
|
|
159
|
+
/** The grid's CSS height; paged grids default to the height of a page of rows. */
|
|
160
|
+
height?: string;
|
|
161
|
+
theme?: "light" | "dark" | "auto";
|
|
162
|
+
density?: "compact" | "default" | "comfortable";
|
|
163
|
+
zebra?: boolean;
|
|
164
|
+
/** Further grid definition fields (rowHeight, statusBar, toolbar, reporting, timeZone, ...), merged last. */
|
|
165
|
+
view?: Partial<GridView>;
|
|
166
|
+
/** Handlers by event name, attached before the grid starts. */
|
|
167
|
+
on?: Readonly<Record<string, (detail: any, grid: EnhancedGrid<R>, event?: CustomEvent) => void>>;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/** A header row above the bottom one: groups with their titles and the ids of the columns they span. */
|
|
171
|
+
export interface GridHeaderGroup {
|
|
172
|
+
readonly title: string;
|
|
173
|
+
readonly columns: readonly string[];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* The controller CanopyX.enhance and CanopyX.grid resolve with: the grid's API plus events by name, records and the restored
|
|
178
|
+
* table. Its addRows and removeRows take records as the controller was given them; the grid's other live methods stay.
|
|
179
|
+
*/
|
|
180
|
+
export interface EnhancedGrid<R = any> extends Omit<DataGrid, "addRows" | "removeRows"> {
|
|
181
|
+
/** The original table, put back by destroy(); null for a grid built in another element. */
|
|
182
|
+
readonly table: HTMLTableElement | null;
|
|
183
|
+
/** Header rows above the bottom one, as levels of groups. */
|
|
184
|
+
readonly headerGroups: readonly (readonly GridHeaderGroup[])[];
|
|
185
|
+
on(name: "init", handler: (detail: { query: GridQuery }, grid: EnhancedGrid<R>) => void): this;
|
|
186
|
+
on(name: "draw" | "order" | "search" | "page" | "length", handler: (detail: GridDrawEvent, grid: EnhancedGrid<R>, event?: CustomEvent) => void): this;
|
|
187
|
+
/** Any canopyx:<name> event of the grid: select, query, state, error, rowActivate, link, columnResize, columnPin, ... */
|
|
188
|
+
on(name: string, handler: (detail: any, grid: EnhancedGrid<R>, event?: CustomEvent) => void): this;
|
|
189
|
+
off(name: string, handler: (...args: any[]) => void): this;
|
|
190
|
+
/** Records as given (a table row's cell texts): all in data order, filtered in the accepted order, or the visible page. A server source returns its last loaded rows. */
|
|
191
|
+
getRows(scope?: "all" | "filtered" | "page"): R[];
|
|
192
|
+
getRow(id: string): R | undefined;
|
|
193
|
+
/** Replaces the records; the sort, search, filters and page stay. Inline data only. */
|
|
194
|
+
setData(data: readonly R[]): Promise<GridQuery>;
|
|
195
|
+
addRows(data: readonly R[]): Promise<GridQuery>;
|
|
196
|
+
removeRows(ids: readonly string[]): Promise<GridQuery>;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/** Turns an existing table into a grid, keeping the table as the script-free fallback; destroy() puts it back. */
|
|
200
|
+
export function enhance(table: HTMLTableElement | string, options?: GridInitOptions<string[]>): Promise<EnhancedGrid<string[]>>;
|
|
201
|
+
/** Builds a grid in an element from records or a URL source; given a table, it enhances it. */
|
|
202
|
+
export function grid<R = any>(element: HTMLElement | string, options: GridInitOptions<R>): Promise<EnhancedGrid<R>>;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// The facet panel of flat grids (docs/facets.md): value lists with counts and ranges with histograms that filter each other.
|
|
2
|
+
import type { GridRow, GridColumnId } from "./grid.js";
|
|
3
|
+
|
|
4
|
+
/** One facet: a column id, or a column with its settings. */
|
|
5
|
+
export type GridFacet<Row extends GridRow = GridRow> = GridColumnId<Row> | {
|
|
6
|
+
column: GridColumnId<Row>;
|
|
7
|
+
/** "list" (text columns by default) or "range" with a histogram (number and date columns by default). */
|
|
8
|
+
kind?: "list" | "range";
|
|
9
|
+
/** The facet's heading; the column's title by default. */
|
|
10
|
+
label?: string;
|
|
11
|
+
/** Values a list shows before "Show N more", 1..200 (default 8). */
|
|
12
|
+
limit?: number;
|
|
13
|
+
/** Bars in a range's histogram, 2..60 (default 16). */
|
|
14
|
+
bins?: number;
|
|
15
|
+
/** "count" (most frequent first) or "value"; omitted uses declared column order, otherwise count. */
|
|
16
|
+
sort?: "count" | "value";
|
|
17
|
+
/** Starts collapsed to its heading. */
|
|
18
|
+
collapsed?: boolean;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
/** The facet panel a grid definition carries (the C# CanopyFacetPanel writes it). */
|
|
22
|
+
export interface GridFacetPanelDefinition<Row extends GridRow = GridRow> {
|
|
23
|
+
/** 1 to 24 distinct columns; a hosted grid's must be reporting facet columns. */
|
|
24
|
+
columns: readonly GridFacet<Row>[];
|
|
25
|
+
/** Beside the grid (default) or above it. */
|
|
26
|
+
position?: "side" | "top";
|
|
27
|
+
/** Starts open (default true); the grid state keeps the reader's choice. */
|
|
28
|
+
open?: boolean;
|
|
29
|
+
/** The reader can collapse the panel (default true). */
|
|
30
|
+
collapsible?: boolean;
|
|
31
|
+
/** A side panel's width, 180..480 pixels (default 260). */
|
|
32
|
+
width?: number;
|
|
33
|
+
/** The panel's heading; "Filter by" by default. */
|
|
34
|
+
label?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/** The host's facet options: the definition's fields, and an element the panel renders into. */
|
|
38
|
+
export interface GridFacetPanelOptions<Row extends GridRow = GridRow> extends Partial<GridFacetPanelDefinition<Row>> {
|
|
39
|
+
/** An element the panel renders into, for a host that lays out the page itself; the grid element stays where it is. */
|
|
40
|
+
target?: HTMLElement;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/** The facet panel's state, from getFacetPanel(). */
|
|
44
|
+
export interface GridFacetPanelState {
|
|
45
|
+
/** Whether the panel is open; null before the facets part has started. */
|
|
46
|
+
readonly open: boolean | null;
|
|
47
|
+
/** The facet columns, in order; empty before the facets part has started. */
|
|
48
|
+
readonly columns: readonly string[];
|
|
49
|
+
/** Facets with a choice. */
|
|
50
|
+
readonly active?: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** Facet panel methods of a flat grid. */
|
|
54
|
+
export interface GridFacetPanelApi {
|
|
55
|
+
getFacetPanel(): GridFacetPanelState;
|
|
56
|
+
/** Opens or collapses the panel; loads the facets part on first use. */
|
|
57
|
+
setFacetPanelOpen(open: boolean): Promise<GridFacetPanelState>;
|
|
58
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
// Conditional formatting of flat grids (docs/conditional-formatting.md). The same schema as the .NET CanopyFormatRule
|
|
2
|
+
// family writes; the browser's rule editor reads and writes it too.
|
|
3
|
+
|
|
4
|
+
/** Every flat-grid filter operator, plus negations, suffixes, patterns, ranges and relative dates in days. */
|
|
5
|
+
export type GridFormatOperator = "eq" | "ne" | "gt" | "ge" | "lt" | "le" | "contains" | "notContains" | "startsWith" | "endsWith" | "like" | "notLike"
|
|
6
|
+
| "matches" | "notMatches" | "in" | "notIn" | "between" | "betweenExclusive" | "isNull" | "isNotNull" | "olderThan" | "withinLast";
|
|
7
|
+
/** A raw operand: text, a finite number or a boolean. Dates are ISO 8601 strings with a time zone. */
|
|
8
|
+
export type GridFormatValue = string | number | boolean;
|
|
9
|
+
/** One test: a column, an operator and operands, or another column to compare with. */
|
|
10
|
+
export interface GridFormatPredicate {
|
|
11
|
+
readonly column: string;
|
|
12
|
+
readonly operator: GridFormatOperator;
|
|
13
|
+
/** None for the null tests, two for ranges, 1..1000 for in/notIn, days for relative dates, one otherwise. */
|
|
14
|
+
readonly values?: readonly GridFormatValue[];
|
|
15
|
+
/** Compare with this column's value instead of values (one-operand comparisons). */
|
|
16
|
+
readonly valueColumn?: string;
|
|
17
|
+
/** How values are read; the column's kind by default. */
|
|
18
|
+
readonly type?: "text" | "number" | "boolean" | "date";
|
|
19
|
+
/** Text compares case-insensitively unless true. */
|
|
20
|
+
readonly caseSensitive?: boolean;
|
|
21
|
+
/** A BCP 47 culture for parsing numbers in text and comparing text. */
|
|
22
|
+
readonly culture?: string;
|
|
23
|
+
}
|
|
24
|
+
/** A condition group: a filter group with a third junction, none. Eight levels, 64 groups and 64 predicates at most. */
|
|
25
|
+
export interface GridFormatCondition {
|
|
26
|
+
readonly operator: "and" | "or" | "none";
|
|
27
|
+
readonly filters?: readonly GridFormatPredicate[];
|
|
28
|
+
readonly groups?: readonly GridFormatCondition[];
|
|
29
|
+
}
|
|
30
|
+
/** An icon name, "auto" (the tone's shape) or "none", or up to four characters of the host's own. */
|
|
31
|
+
export type GridFormatIcon = "auto" | "none" | "up" | "down" | "check" | "cross" | "warning" | "info" | "dot" | "circle" | "triangle" | "square" | "diamond"
|
|
32
|
+
| "flag" | "star" | "minus" | "plus" | "clock" | (string & {});
|
|
33
|
+
/** A data bar: absent bounds run from zero (or the lowest value) to the highest value of the rows in hand. */
|
|
34
|
+
export interface GridFormatDataBar { readonly minimum?: number; readonly maximum?: number; readonly tone?: string; readonly showValue?: boolean; }
|
|
35
|
+
/** A colour scale stop at the lowest or highest value, at a number, or at a percentage of the range. */
|
|
36
|
+
export interface GridFormatScaleStop { readonly type: "min" | "max" | "number" | "percent"; readonly value?: number; readonly tone: string; }
|
|
37
|
+
export interface GridFormatColorScale {
|
|
38
|
+
readonly stops: readonly [GridFormatScaleStop, GridFormatScaleStop] | readonly [GridFormatScaleStop, GridFormatScaleStop, GridFormatScaleStop];
|
|
39
|
+
}
|
|
40
|
+
/** A threshold band: values up to its inclusive upper bound take its tone; the last band may leave its bound open. */
|
|
41
|
+
export interface GridFormatBand { readonly upperBound?: number; readonly tone: string; readonly label?: string; readonly icon?: GridFormatIcon; }
|
|
42
|
+
/** Theme tones with an emphasis, an icon, a badge and a cue, or one of a bar, a scale and bands; className and css are the escape hatch. */
|
|
43
|
+
export interface GridFormatStyle {
|
|
44
|
+
readonly tone?: string;
|
|
45
|
+
readonly emphasis?: "fill" | "text" | "strong";
|
|
46
|
+
readonly icon?: GridFormatIcon;
|
|
47
|
+
readonly badge?: string;
|
|
48
|
+
readonly cue?: string;
|
|
49
|
+
readonly bar?: GridFormatDataBar;
|
|
50
|
+
readonly scale?: GridFormatColorScale;
|
|
51
|
+
readonly bands?: readonly GridFormatBand[];
|
|
52
|
+
readonly className?: string;
|
|
53
|
+
readonly css?: Readonly<Record<string, string>>;
|
|
54
|
+
}
|
|
55
|
+
/** A rule: identity, condition (absent matches every row), target and style. Rules apply in order; the first rule that sets an aspect of a target wins it. */
|
|
56
|
+
export interface GridFormatRule {
|
|
57
|
+
readonly id: string;
|
|
58
|
+
/** The legend entry and default screen reader description. */
|
|
59
|
+
readonly label?: string;
|
|
60
|
+
/** What screen readers hear on a formatted cell. */
|
|
61
|
+
readonly description?: string;
|
|
62
|
+
readonly enabled?: boolean;
|
|
63
|
+
readonly when?: GridFormatCondition;
|
|
64
|
+
/** The cell a cell rule paints and the value bars, scales and bands read. */
|
|
65
|
+
readonly column?: string;
|
|
66
|
+
readonly target?: "cell" | "row" | "columns";
|
|
67
|
+
readonly columns?: readonly string[];
|
|
68
|
+
/** Follow the column into the record drawer and the phone's hidden fields (default true). */
|
|
69
|
+
readonly details?: boolean;
|
|
70
|
+
readonly style: GridFormatStyle;
|
|
71
|
+
readonly stopIfTrue?: boolean;
|
|
72
|
+
}
|
|
73
|
+
/** A legend of the labelled rules, and the rule editor in the more menu. */
|
|
74
|
+
export interface GridFormatOptions { readonly legend?: boolean; readonly editor?: boolean; }
|
|
75
|
+
/** A cell's or record's resolved format in export records, for writers that paint (a styled spreadsheet, a print snapshot). */
|
|
76
|
+
export interface GridExportFormat {
|
|
77
|
+
readonly rules: readonly string[];
|
|
78
|
+
readonly tone?: string;
|
|
79
|
+
readonly icon?: string;
|
|
80
|
+
readonly badge?: string;
|
|
81
|
+
readonly cue?: string;
|
|
82
|
+
readonly band?: string;
|
|
83
|
+
/** Where the value lies between the bar's bounds, 0..1, and the bar's tone. */
|
|
84
|
+
readonly bar?: { readonly fraction: number; readonly tone: string };
|
|
85
|
+
/** A colour scale's CSS colour, mixed from theme tone variables. */
|
|
86
|
+
readonly color?: string;
|
|
87
|
+
readonly description?: string;
|
|
88
|
+
}
|