@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
package/JavaScript/protocol.d.ts
CHANGED
|
@@ -8,7 +8,9 @@ export type SortDirection = "asc" | "desc";
|
|
|
8
8
|
export interface CanopyBadge { text: string; tone?: string; title?: string; }
|
|
9
9
|
/** Ordered visual history metadata; raw cell values still drive queries and exports. */
|
|
10
10
|
export interface CellPeriod { period: string; value?: number | null; state?: string | null; tone?: string; }
|
|
11
|
-
|
|
11
|
+
import type { StructuredCell, RecordPanelDefinition } from "./records.js";
|
|
12
|
+
/** A cell: a value with display text, tooltip, tone and badges; it may hold a structured value or a record link (records.d.ts). */
|
|
13
|
+
export interface CanopyCell extends StructuredCell {
|
|
12
14
|
value?: CellValue;
|
|
13
15
|
text?: string;
|
|
14
16
|
/** Alternate flat-grid search text, independent of display, typed queries and export. */
|
|
@@ -20,6 +22,8 @@ export interface CanopyCell {
|
|
|
20
22
|
secondary?: string;
|
|
21
23
|
/** At most 4096 ordered periods for a flat-grid history presenter. */
|
|
22
24
|
series?: CellPeriod[];
|
|
25
|
+
/** Sort key when it differs from the value (text or a number); filters, value lists, search and display keep reading value and text. */
|
|
26
|
+
sort?: string | number;
|
|
23
27
|
}
|
|
24
28
|
export type Cell = CellValue | CanopyCell;
|
|
25
29
|
|
|
@@ -51,6 +55,8 @@ interface NodeDefinition {
|
|
|
51
55
|
badges?: CanopyBadge[];
|
|
52
56
|
flags?: string[];
|
|
53
57
|
data?: Record<string, string>;
|
|
58
|
+
/** Values of the view's record fields (record.fields), shown in the record drawer only. */
|
|
59
|
+
fields?: Record<string, Cell>;
|
|
54
60
|
expanded?: boolean;
|
|
55
61
|
className?: string;
|
|
56
62
|
}
|
|
@@ -67,6 +73,85 @@ export interface CanopyColumn {
|
|
|
67
73
|
sortable?: boolean;
|
|
68
74
|
hidden?: boolean;
|
|
69
75
|
editable?: boolean;
|
|
76
|
+
/** Fit the visible rows' content (the tree tools part measures it); width is the fallback until then. Otherwise width is preferred. */
|
|
77
|
+
autoWidth?: boolean;
|
|
78
|
+
/** The width stays during fitting; the reader can still resize the column. */
|
|
79
|
+
fixed?: boolean;
|
|
80
|
+
/** Share of spare width, given before the tree column. */
|
|
81
|
+
flex?: number;
|
|
82
|
+
/** What content measuring reads. Default content. */
|
|
83
|
+
autoSize?: "content" | "header" | "none";
|
|
84
|
+
/** How the column gives way when narrow: 0-1 essential, 10000+ optional; or the named levels. */
|
|
85
|
+
priority?: "essential" | "normal" | "optional" | number;
|
|
86
|
+
/** Retained during responsive fitting. */
|
|
87
|
+
alwaysVisible?: boolean;
|
|
88
|
+
/** Hover tooltip: "auto" shows a cell's full value while it is cut off; a declared column id shows that column's text. */
|
|
89
|
+
tooltip?: string;
|
|
90
|
+
/** The tree column pins left by default and null lets it scroll; other columns pin left (after the tree column) or right. */
|
|
91
|
+
pinned?: "left" | "right" | null;
|
|
92
|
+
/** The name of a cell renderer a plugin registers (cellRenderers); an unregistered name keeps the built-in painter. */
|
|
93
|
+
renderer?: string;
|
|
94
|
+
/** The record drawer section of the column. */
|
|
95
|
+
section?: string;
|
|
96
|
+
/** false keeps the column out of the record drawer. Default true. */
|
|
97
|
+
drawer?: boolean;
|
|
98
|
+
}
|
|
99
|
+
/** Per-control tree toolbar switches in the view document; an absent switch keeps its control. */
|
|
100
|
+
export interface TreeToolbarControls {
|
|
101
|
+
filters?: boolean;
|
|
102
|
+
columns?: boolean;
|
|
103
|
+
views?: boolean;
|
|
104
|
+
export?: boolean;
|
|
105
|
+
more?: boolean;
|
|
106
|
+
/** The match navigator and the Highlight matches switch of a view with searchHighlight. */
|
|
107
|
+
matches?: boolean;
|
|
108
|
+
/** The Layout menu of a view with layout options. */
|
|
109
|
+
layout?: boolean;
|
|
110
|
+
}
|
|
111
|
+
/** Search-hit highlighting (docs/search-highlight.md). true in a view document uses every default. */
|
|
112
|
+
export interface SearchHighlightOptions {
|
|
113
|
+
/** Marks shown when the view opens; the reader can switch them. Default true. */
|
|
114
|
+
enabled?: boolean;
|
|
115
|
+
/** Mark quick-search text. Default true. */
|
|
116
|
+
search?: boolean;
|
|
117
|
+
/** Mark the values a flat grid's column filters match, styled apart from search hits. Default true. */
|
|
118
|
+
filters?: boolean;
|
|
119
|
+
/** Compare case exactly when marking. Default false: the search's own case folding. */
|
|
120
|
+
matchCase?: boolean;
|
|
121
|
+
/** A letter with accents matches its base letter when marking. Default false. */
|
|
122
|
+
ignoreAccents?: boolean;
|
|
123
|
+
/** The shortest term that is marked, 1..32. Default 1. */
|
|
124
|
+
minLength?: number;
|
|
125
|
+
/** A tone per column id for its filter hits. */
|
|
126
|
+
filterTones?: Record<string, string>;
|
|
127
|
+
}
|
|
128
|
+
/** How a view lays out its columns (docs/layout-modes.md). Trees offer fit and scroll. */
|
|
129
|
+
export type LayoutMode = "fit" | "scroll" | "cards";
|
|
130
|
+
/** Row spacing; "default" is the Normal density. */
|
|
131
|
+
export type LayoutDensity = "compact" | "default" | "comfortable";
|
|
132
|
+
/** The Layout menu of a view: the layouts the reader can choose, and the starting layout and density. */
|
|
133
|
+
export interface LayoutOptions<M extends LayoutMode = LayoutMode> {
|
|
134
|
+
mode?: M;
|
|
135
|
+
modes?: readonly M[];
|
|
136
|
+
density?: LayoutDensity;
|
|
137
|
+
}
|
|
138
|
+
/** The reader's layout choice, as saved state keeps it. */
|
|
139
|
+
export interface LayoutState { mode: LayoutMode; density: LayoutDensity; }
|
|
140
|
+
/** The current layout and the layouts the view offers. */
|
|
141
|
+
export interface LayoutInfo extends LayoutState { readonly modes: readonly LayoutMode[]; }
|
|
142
|
+
/** The match count: total matches (in the loaded rows while complete is false) and the 1-based current match, or 0. */
|
|
143
|
+
export interface MatchInfo { readonly enabled: boolean; readonly total: number; readonly current: number; readonly complete: boolean; }
|
|
144
|
+
/** Search highlighting and layout methods of every tree and flat grid; they reject when the view does not declare the feature. */
|
|
145
|
+
export interface ViewModeMethods {
|
|
146
|
+
getLayout(): LayoutInfo;
|
|
147
|
+
/** Switches the layout and/or density, keeping the query, selection, focus and the first row in view. */
|
|
148
|
+
setLayout(change: Partial<LayoutState>): Promise<LayoutInfo>;
|
|
149
|
+
getMatches(): MatchInfo;
|
|
150
|
+
/** The Highlight matches switch. */
|
|
151
|
+
setSearchHighlight(enabled: boolean): Promise<void>;
|
|
152
|
+
/** Moves to the next match and scrolls its row into view; focus (default true) focuses its cell. False when nothing matches. */
|
|
153
|
+
nextMatch(options?: { focus?: boolean }): Promise<boolean>;
|
|
154
|
+
previousMatch(options?: { focus?: boolean }): Promise<boolean>;
|
|
70
155
|
}
|
|
71
156
|
export interface CanopyFilter {
|
|
72
157
|
id: string;
|
|
@@ -104,10 +189,10 @@ export type InlineNode = LeafNode | DetailNode | InlineBranch<InlineNode>;
|
|
|
104
189
|
|
|
105
190
|
/** Names accepted by the interactive runtime; omitted translations use English. */
|
|
106
191
|
export type LabelName =
|
|
107
|
-
| "gridPaging" | "gridPageRange" | "gridPageNumber" | "gridPageLength" | "gridFirstPage" | "gridPreviousPage" | "gridNextPage" | "gridLastPage"
|
|
192
|
+
| "gridPaging" | "gridPageRange" | "gridPageNumber" | "gridPageLength" | "gridFirstPage" | "gridPreviousPage" | "gridNextPage" | "gridLastPage" | "gridPageInfo" | "gridPageInfoFiltered" | "gridPageButton"
|
|
108
193
|
| "gridUnknownCount" | "gridMatchedCount" | "gridCursorRange"
|
|
109
194
|
| "gridResultCount" | "gridClearQuery" | "gridRemoveSearch" | "gridGroupedFilters" | "gridRemoveGroup" | "gridRemoveCondition"
|
|
110
|
-
| "gridExport" | "gridFilteredResults" | "gridSelectedRows" | "gridAllResults" | "gridDownloadCsv" | "gridCopy" | "gridDetails"
|
|
195
|
+
| "gridExport" | "gridFilteredResults" | "gridSelectedRows" | "gridAllResults" | "gridVisibleRows" | "gridAllRows" | "gridDownloadCsv" | "gridCopy" | "gridDetails"
|
|
111
196
|
| "searchPlaceholder" | "searchResults" | "searchResultCount" | "searchResultCountOfTotal"
|
|
112
197
|
| "searchResultCountOfMany" | "searchNoResults" | "searchTooShort" | "searchWordTooShort" | "searchFailed"
|
|
113
198
|
| "columns" | "visibleColumns" | "resizeColumn" | "columnWidth" | "loading" | "loadError" | "queryFailed"
|
|
@@ -125,8 +210,10 @@ export type LabelName =
|
|
|
125
210
|
| "gridRenameView" | "gridDefaultView" | "gridClearDefaultView" | "gridDefaultViewName" | "gridNoDefaultView" | "gridDefaultViewOption"
|
|
126
211
|
| "gridSelection" | "gridSelectPage" | "gridSelectMatching" | "gridClearSelection" | "gridSelectionCount"
|
|
127
212
|
| "gridSelectionQueryCount" | "gridSelectionQueryUnknown" | "gridSelectRecord"
|
|
128
|
-
| "gridGroupHeading" | "gridGroupMissing" | "gridGroupExpand" | "gridGroupCollapse" | "gridSummary" | "gridGroupOrder"
|
|
129
|
-
| "gridExportProgress" | "gridExportReading" | "gridExportCancelled" | "gridCancelExport" | "gridPrint"
|
|
213
|
+
| "gridGroupHeading" | "gridGroupMissing" | "gridGroupExpand" | "gridGroupCollapse" | "gridSummary" | "gridGroupOrder" | "gridAggregateCount" | "gridAggregateSum" | "gridAggregateAverage" | "gridAggregateMinimum" | "gridAggregateMaximum" | "gridGroupBy" | "gridUngroup" | "gridGroupDrop" | "gridExpandAll" | "gridCollapseAll" | "gridExpandLevel" | "gridCollapseLevel" | "gridGroupMove" | "gridGroupSortBy" | "gridGroupSortValue" | "gridGroupSortAggregate" | "gridSelectGroup" | "gridAggregateDistinct" | "gridShowDetail" | "gridHideDetail" | "gridDetailOf" | "gridDetailFailed"
|
|
214
|
+
| "gridExportProgress" | "gridExportReading" | "gridExportCancelled" | "gridCancelExport" | "gridNoExportColumns" | "gridPrint"
|
|
215
|
+
| "matchesHighlight" | "matchesCount" | "matchesPosition" | "matchesNone" | "matchesLoaded" | "matchesPrevious" | "matchesNext" | "matchesAnnounce"
|
|
216
|
+
| "layoutMenu" | "layoutFit" | "layoutScroll" | "layoutCards" | "layoutDensity" | "layoutCompact" | "layoutNormal" | "layoutComfortable" | "layoutChanged" | "layoutSort"
|
|
130
217
|
| "gridFitContent"
|
|
131
218
|
| "gridUnpin"
|
|
132
219
|
| "gridWhere"
|
|
@@ -140,7 +227,37 @@ export type LabelName =
|
|
|
140
227
|
| "gridOfTheseAreTrue"
|
|
141
228
|
| "gridOfThese"
|
|
142
229
|
| "gridGroupCount"
|
|
143
|
-
|
|
230
|
+
// The editing part's labels (docs/editing.md).
|
|
231
|
+
| "gridEditCell" | "gridEditSave" | "gridEditCancel" | "gridEditDiscard" | "gridEditUndo" | "gridEditRedo" | "gridEditEdited" | "gridEditChanges"
|
|
232
|
+
| "gridEditErrors" | "gridEditSaving" | "gridEditSaved" | "gridEditFailed" | "gridEditRequired" | "gridEditNumber" | "gridEditDate" | "gridEditMin"
|
|
233
|
+
| "gridEditMax" | "gridEditStep" | "gridEditMinLength" | "gridEditMaxLength" | "gridEditPattern" | "gridEditChoice" | "gridEditConflict" | "gridEditRejected"
|
|
234
|
+
| "gridEditNotSaved" | "gridEditNoMatches" | "gridEditSearching" | "gridEditUndone" | "gridEditRedone" | "gridEditNone"
|
|
235
|
+
| "gridMore" | "gridDone" | "gridClearAll" | "gridRows" | "gridResultNoun" | "gridSearchNoun" | "gridChart" | "gridColumnMenu" | "gridSortAscending" | "gridSortDescending" | "gridClearSort" | "gridFilterColumn" | "gridHideColumn" | "gridGroupedBy" | "gridRemoveGrouping" | "gridSelectAllValues" | "gridFilterValues" | "gridAddCondition" | "gridAddGroup" | "gridAnd" | "gridOr" | "gridEditAsText" | "gridFilterText" | "gridDeepFilters" | "gridToday" | "gridYesterday" | "gridLastSevenDays" | "gridLastThirtyDays" | "gridThisMonth" | "gridDateRange" | "gridEmpty" | "gridEmptyReason" | "gridNoMatches" | "gridNoMatchesReason" | "gridRetry" | "gridLoadFailed" | "gridAll" | "gridPageOf" | "gridStatusCount" | "gridDetailsSection" | "gridPreviousRecord" | "gridNextRecord" | "gridShowMore" | "gridNoData" | "gridPeriodRange" | "gridHealthy"
|
|
236
|
+
/** Conditional formatting (the formatting and rule editor parts of flat grids); trees ignore them. */
|
|
237
|
+
| "formatRules" | "formatLegend" | "formatUpTo" | "formatAbove" | "formatHiddenFlagged" | "formatRule" | "formatAddRule" | "formatEditRule"
|
|
238
|
+
| "formatDeleteRule" | "formatMoveUp" | "formatMoveDown" | "formatEnableRule" | "formatNoRules" | "formatName" | "formatDescription" | "formatOnlyRowsWhere"
|
|
239
|
+
| "formatEveryRow" | "formatNone" | "formatApplyTo" | "formatTargetCell" | "formatTargetRow" | "formatTargetColumns" | "formatStyle" | "formatHighlight"
|
|
240
|
+
| "formatDataBar" | "formatColorScale" | "formatBands" | "formatTone" | "formatEmphasis" | "formatFill" | "formatTextOnly" | "formatStrong"
|
|
241
|
+
| "formatIcon" | "formatNoIcon" | "formatAutomatic" | "formatBadge" | "formatCue" | "formatLowest" | "formatMidpoint" | "formatHighest"
|
|
242
|
+
| "formatAddBand" | "formatRemoveBand" | "formatSave" | "formatCancel" | "formatShowLegend" | "formatInvalid" | "formatMatchCase" | "formatToneDanger"
|
|
243
|
+
| "formatToneWarning" | "formatToneSuccess" | "formatToneInfo" | "formatToneNeutral" | "formatToneMuted" | "formatNotContains" | "formatEndsWith" | "formatNotIn"
|
|
244
|
+
| "formatBetween" | "formatLike" | "formatMatches" | "formatOlderThan" | "formatWithinLast" | "formatNotLike" | "formatNotMatches" | "formatBetweenExclusive"
|
|
245
|
+
/** Cell ranges and the clipboard (docs/cell-ranges.md). */
|
|
246
|
+
| "gridCellRangeSelected" | "gridCellRangesSelected" | "gridCellRangeCleared" | "gridCopyCells" | "gridCopyCellsWithHeaders" | "gridPasteCells"
|
|
247
|
+
| "gridSelectAllCells" | "gridCellsCopied" | "gridCellsPasted" | "gridPasteRefused" | "gridPasteReadOnly" | "gridPasteType" | "gridPasteReport"
|
|
248
|
+
| "gridPasteCell" | "gridFillHandle" | "gridCellsFilled" | "gridCellMenu" | "gridClearCellRanges"
|
|
249
|
+
/** Linked views (docs/linked-views.md). */
|
|
250
|
+
| "linkFilteredBy" | "linkRemoveFilter" | "linkFiltered" | "linkHighlighted" | "linkHighlightedRows" | "linkCleared"
|
|
251
|
+
/** The record panel (docs/record-panel.md). */
|
|
252
|
+
| "recordBack" | "recordBackTo" | "recordTrail" | "recordShowing" | "recordTabs" | "recordSections" | "recordOtherFields" | "recordShowEmpty" | "recordHideEmpty" | "recordActions" | "recordCopyValues" | "recordCopyJson" | "recordCopyLink" | "recordCopied" | "recordPrint" | "recordExportCsv" | "recordExportJson" | "recordOpenAll" | "recordLoadMore" | "recordCount" | "recordItems" | "recordMore" | "recordShowAll" | "recordRetry" | "recordLoadFailed" | "recordUnavailable" | "recordField" | "recordValue" | "recordSection" | "recordBefore" | "recordAfter" | "recordAdded" | "recordRemoved" | "recordChanged"
|
|
253
|
+
/** The calendar and resource timeline (the calendar and timeline parts of flat grids). */
|
|
254
|
+
| "calendarToday" | "calendarPrevious" | "calendarNext" | "calendarViews" | "calendarMonth" | "calendarWeek" | "calendarDay" | "calendarDays"
|
|
255
|
+
| "calendarAgenda" | "calendarYear" | "calendarTimeline" | "calendarGoTo" | "calendarAllDay" | "calendarMore" | "calendarMoreLabel" | "calendarDayEvents"
|
|
256
|
+
| "calendarNoEvents" | "calendarEvents" | "calendarShowing" | "calendarRepeats" | "calendarTruncated" | "calendarLoading" | "calendarLoadError" | "calendarNow"
|
|
257
|
+
| "calendarZoom" | "calendarZoomHour" | "calendarZoomDay" | "calendarZoomWeek" | "calendarZoomMonth" | "calendarZoomQuarter" | "calendarResources" | "calendarCapacity"
|
|
258
|
+
| "calendarCapacityAt" | "calendarBusy" | "calendarOverlaps" | "calendarUnavailable" | "calendarOutsideHours" | "calendarConflict" | "calendarNotAllowed" | "calendarMoved"
|
|
259
|
+
| "calendarResized" | "calendarSeriesMoved" | "calendarSeriesTime" | "calendarMoveHelp" | "calendarEdit" | "calendarSaveFailed" | "calendarExport" | "calendarTimeRange" | "calendarSelected"
|
|
260
|
+
| "calendarLane" | "calendarHighlighted";
|
|
144
261
|
export type CanopyLabels = Partial<Record<LabelName, string>>;
|
|
145
262
|
|
|
146
263
|
export interface InlineSourceDefinition { kind: "inline"; }
|
|
@@ -169,8 +286,20 @@ interface ViewDefinitionBase {
|
|
|
169
286
|
filters?: CanopyFilter[];
|
|
170
287
|
timeZone?: TimeZone;
|
|
171
288
|
pinTreeColumn?: boolean;
|
|
289
|
+
/** Marks the search box's words in the tree column (docs/search-highlight.md). */
|
|
290
|
+
searchHighlight?: boolean | SearchHighlightOptions;
|
|
291
|
+
/** The Layout menu: fit and scroll, and the density (docs/layout-modes.md). */
|
|
292
|
+
layout?: LayoutOptions<"fit" | "scroll">;
|
|
293
|
+
/** Per-control toolbar switches (the search box is the search property). */
|
|
294
|
+
toolbar?: TreeToolbarControls;
|
|
295
|
+
/** Identities of registered export formats the Export menu offers after CSV, in order. */
|
|
296
|
+
exportFormats?: string[];
|
|
297
|
+
/** A tree whose visible rows fit is as tall as its rows; false keeps the host height. Default true. */
|
|
298
|
+
autoHeight?: boolean;
|
|
172
299
|
stateKey?: string;
|
|
173
300
|
deepLink?: boolean;
|
|
301
|
+
/** The record panel of the tree's drawer (records.d.ts, docs/record-panel.md). */
|
|
302
|
+
record?: RecordPanelDefinition;
|
|
174
303
|
labels?: CanopyLabels;
|
|
175
304
|
dragDrop?: boolean;
|
|
176
305
|
contextActions?: ContextAction[];
|
|
@@ -221,6 +350,10 @@ export interface ViewState {
|
|
|
221
350
|
filters: string[];
|
|
222
351
|
timeZone: TimeZone;
|
|
223
352
|
pinTreeColumn: boolean;
|
|
353
|
+
/** The reader's layout, in a view with layout options. */
|
|
354
|
+
layout?: LayoutState;
|
|
355
|
+
/** The reader's Highlight matches switch, in a view with searchHighlight. */
|
|
356
|
+
highlight?: boolean;
|
|
224
357
|
focus: string[] | null;
|
|
225
358
|
anchor: { path: string[]; offset: number } | null;
|
|
226
359
|
checkboxes?: CheckMode;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
// The record panel (docs/record-panel.md): structured values, record-only fields, the record drawer's layout, record links,
|
|
2
|
+
// records loaded on demand (the gridRecord exchange) and the extension points of the drawer.
|
|
3
|
+
import type { Cell, CellValue } from "./protocol.js";
|
|
4
|
+
|
|
5
|
+
/** A link from a value to another record: of the value's own view, or of the grid or tree with id view. */
|
|
6
|
+
export interface RecordRef {
|
|
7
|
+
readonly id: string;
|
|
8
|
+
readonly view?: string;
|
|
9
|
+
/** A tree record's id path from a top-level node, ending with id, so the tree can expand to it. */
|
|
10
|
+
readonly path?: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
/** One named value of an object value. */
|
|
13
|
+
export interface RecordFieldValue { readonly name: string; readonly value: Cell; readonly kind?: "number" | "datetime"; }
|
|
14
|
+
/** A field's value before and after a change. Lists (items) on both sides mark the items removed and added. */
|
|
15
|
+
export interface RecordChange { readonly name: string; readonly before: Cell; readonly after: Cell; readonly kind?: "number" | "datetime"; }
|
|
16
|
+
/** One timeline event. */
|
|
17
|
+
export interface RecordEvent {
|
|
18
|
+
readonly time?: string; readonly summary: string; readonly actor?: string; readonly kind?: string; readonly tone?: string;
|
|
19
|
+
readonly ref?: RecordRef; readonly changes?: readonly RecordChange[];
|
|
20
|
+
}
|
|
21
|
+
/** A column of a collection: a grid column (rows) or a tree column (roots). */
|
|
22
|
+
export interface RecordListColumn {
|
|
23
|
+
readonly id: string; readonly title: string; readonly kind?: "text" | "number" | "datetime"; readonly width?: number;
|
|
24
|
+
readonly sortable?: boolean; readonly presenter?: unknown; readonly [option: string]: unknown;
|
|
25
|
+
}
|
|
26
|
+
/** A row of a collection. */
|
|
27
|
+
export interface RecordListRow { readonly id: string; readonly cells: Readonly<Record<string, Cell>>; readonly [field: string]: unknown; }
|
|
28
|
+
/** The grid whose records a collection's rows are: rows open their record there, and Open all in grid filters it. */
|
|
29
|
+
export interface RecordTarget {
|
|
30
|
+
readonly view: string; readonly column?: string; readonly values?: readonly CellValue[];
|
|
31
|
+
readonly filters?: readonly { readonly column: string; readonly operator: string; readonly values: readonly CellValue[] }[];
|
|
32
|
+
}
|
|
33
|
+
/** A collection of records: rows (or tree roots), the total when rows are the first ones, and the target grid. */
|
|
34
|
+
export interface RecordList {
|
|
35
|
+
readonly columns: readonly RecordListColumn[];
|
|
36
|
+
readonly rows?: readonly RecordListRow[];
|
|
37
|
+
readonly roots?: readonly unknown[];
|
|
38
|
+
readonly total?: number; readonly pageLength?: number; readonly pageSize?: number;
|
|
39
|
+
readonly target?: RecordTarget;
|
|
40
|
+
}
|
|
41
|
+
/** The structured members a cell object may carry (at most one of items, fields, records, events and changes) and a link. */
|
|
42
|
+
export interface StructuredCell {
|
|
43
|
+
/** A list value: chips in the panel; the structured presenter summarises it in the grid. */
|
|
44
|
+
items?: Cell[];
|
|
45
|
+
/** An object value: a nested property list. */
|
|
46
|
+
fields?: RecordFieldValue[];
|
|
47
|
+
/** A collection: a nested grid or tree, cards on phones, a table in print. */
|
|
48
|
+
records?: RecordList;
|
|
49
|
+
/** A timeline. */
|
|
50
|
+
events?: RecordEvent[];
|
|
51
|
+
/** Before/after values. */
|
|
52
|
+
changes?: RecordChange[];
|
|
53
|
+
/** A link to another record. */
|
|
54
|
+
ref?: RecordRef;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** A record-only field: a value the drawer shows that is not a grid column. */
|
|
58
|
+
export interface RecordFieldDefinition {
|
|
59
|
+
readonly id: string; readonly title: string; readonly kind?: "text" | "number" | "datetime";
|
|
60
|
+
/** A flat-grid presenter descriptor (the grid runtimes apply it). */
|
|
61
|
+
readonly presenter?: unknown; readonly wrap?: boolean; readonly section?: string;
|
|
62
|
+
}
|
|
63
|
+
export interface RecordSectionDefinition {
|
|
64
|
+
readonly id: string; readonly label: string; readonly fields?: readonly string[]; readonly collapsed?: boolean;
|
|
65
|
+
/** A plugin's drawerSections entry or the host's recordSections entry that draws content above the fields. */
|
|
66
|
+
readonly renderer?: string; readonly sections?: readonly RecordSectionDefinition[];
|
|
67
|
+
}
|
|
68
|
+
export interface RecordTabDefinition { readonly id: string; readonly label: string; readonly sections: readonly string[]; }
|
|
69
|
+
/** The view's record panel (view.record). */
|
|
70
|
+
export interface RecordPanelDefinition {
|
|
71
|
+
readonly fields?: readonly RecordFieldDefinition[];
|
|
72
|
+
readonly header?: { readonly status?: string; readonly facts?: readonly string[] };
|
|
73
|
+
readonly sections?: readonly RecordSectionDefinition[];
|
|
74
|
+
readonly tabs?: readonly RecordTabDefinition[];
|
|
75
|
+
/** Empty fields hide until the reader shows them. Default true. */
|
|
76
|
+
readonly hideEmpty?: boolean;
|
|
77
|
+
/** A jump list of sections; absent shows it from four sections. */
|
|
78
|
+
readonly jumpList?: boolean;
|
|
79
|
+
/** Record deep links (#record=<view>:<id>, or the key given). */
|
|
80
|
+
readonly deepLink?: true | { readonly key?: string };
|
|
81
|
+
readonly source?: { readonly kind: "inline" | "host" } | { readonly kind: "sidecar"; readonly base: string; readonly shards: number };
|
|
82
|
+
readonly actions?: { readonly copy?: boolean; readonly print?: boolean; readonly export?: boolean; readonly link?: boolean };
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** The request for a record's details: the record, a collection field's next rows (field, offset, limit), or its row too. */
|
|
86
|
+
export interface GridRecordQuery {
|
|
87
|
+
readonly protocol: "canopyx/2"; readonly type: "gridRecordQuery"; readonly view: string; readonly id: string;
|
|
88
|
+
readonly revision?: string; readonly field?: string; readonly offset?: number; readonly limit?: number; readonly row?: true;
|
|
89
|
+
}
|
|
90
|
+
/** A record's details. Plain objects with cells, fields and row are accepted as well. */
|
|
91
|
+
export interface GridRecord {
|
|
92
|
+
readonly protocol?: "canopyx/2"; readonly type?: "gridRecord"; readonly view?: string; readonly id?: string; readonly revision?: string;
|
|
93
|
+
readonly cells?: Readonly<Record<string, Cell>>; readonly fields?: Readonly<Record<string, Cell>>;
|
|
94
|
+
readonly row?: RecordListRow;
|
|
95
|
+
}
|
|
96
|
+
/** Loads a record's details when its drawer opens (the loadRecord option, or a hosted source's record hook). */
|
|
97
|
+
export type RecordLoader = (request: GridRecordQuery, options: { signal: AbortSignal }) => GridRecord | null | PromiseLike<GridRecord | null>;
|
|
98
|
+
/** The context of a drawer section renderer. */
|
|
99
|
+
export interface RecordSectionContext {
|
|
100
|
+
readonly section: string; readonly view: string; readonly api: unknown; readonly labels: Readonly<Record<string, string>>;
|
|
101
|
+
readonly signal: AbortSignal; readonly payload: GridRecord | null;
|
|
102
|
+
/** Every field's value, columns and record fields, by id. */
|
|
103
|
+
readonly values: Readonly<Record<string, Cell | undefined>>;
|
|
104
|
+
/** True while the record prints. */
|
|
105
|
+
readonly print: boolean; readonly width: number;
|
|
106
|
+
onDispose(cleanup: () => void): void;
|
|
107
|
+
}
|
|
108
|
+
/** Draws a drawer section's content (a chart, for example) into element. */
|
|
109
|
+
export type RecordSectionRenderer = (record: Readonly<{ id: string; cells?: Readonly<Record<string, Cell>>; fields?: Readonly<Record<string, Cell>>; label?: string }>,
|
|
110
|
+
element: HTMLElement, context: RecordSectionContext) => void | PromiseLike<void>;
|
|
111
|
+
/** An action of the record panel's actions menu. */
|
|
112
|
+
export interface RecordAction {
|
|
113
|
+
readonly label: string;
|
|
114
|
+
run(context: { readonly record: Readonly<{ id: string; cells?: Readonly<Record<string, Cell>>; fields?: Readonly<Record<string, Cell>> }>; readonly view: string; readonly api: unknown;
|
|
115
|
+
readonly payload: GridRecord | null; readonly signal: AbortSignal }): void | PromiseLike<void>;
|
|
116
|
+
}
|
|
117
|
+
/** The canopyx:openAll event's detail (and onOpenAll's argument): cancel it to filter the target grid yourself. */
|
|
118
|
+
export interface RecordOpenAll {
|
|
119
|
+
readonly view: string; readonly ids: readonly string[]; readonly field: string; readonly record: string; readonly total: number;
|
|
120
|
+
readonly filters: readonly { readonly column: string; readonly operator: string; readonly values: readonly CellValue[] }[] | null;
|
|
121
|
+
}
|
|
122
|
+
/** Options that open a record (openRecord). */
|
|
123
|
+
export interface OpenRecordOptions { readonly returnFocus?: Element | null; readonly path?: readonly string[]; readonly tab?: string; }
|
|
124
|
+
/** Host options of the record panel, on grids and trees. */
|
|
125
|
+
export interface RecordPanelOptions {
|
|
126
|
+
/** Loads a record's details when its drawer opens; used whatever the declared source. */
|
|
127
|
+
loadRecord?: RecordLoader;
|
|
128
|
+
/** Section renderers by name, beside the plugins' drawerSections. */
|
|
129
|
+
recordSections?: Readonly<Record<string, RecordSectionRenderer>>;
|
|
130
|
+
/** Actions of the record actions menu, after the built-in ones. */
|
|
131
|
+
recordActions?: readonly RecordAction[];
|
|
132
|
+
/** Open all in grid: return false (or cancel canopyx:openAll) to handle it yourself. */
|
|
133
|
+
onOpenAll?: (event: RecordOpenAll) => boolean | void;
|
|
134
|
+
/** Print one record: return false (or cancel canopyx:recordPrint) to print the sheet yourself. */
|
|
135
|
+
onRecordPrint?: (event: { readonly id: string; readonly element: HTMLElement; readonly dispose: () => void }) => boolean | void;
|
|
136
|
+
}
|
package/README.md
CHANGED
|
@@ -19,14 +19,15 @@ Turn application data into searchable trees, sortable tables and standalone HTML
|
|
|
19
19
|
- **HTML reports** that include their own runtime and data and can be opened from disk or a file share.
|
|
20
20
|
- **Application views** backed by paged or cursor-based data sources, with selection and detail callbacks.
|
|
21
21
|
- **Email and print tables** rendered from the same .NET view without JavaScript.
|
|
22
|
+
- **Calendars and resource timelines** of the same records: month, week, day, agenda and year views, resources grouped as a tree with capacity per group, recurring events, drag to reschedule through the grid's editing, and iCalendar export.
|
|
22
23
|
|
|
23
|
-

|
|
24
25
|
|
|
25
26
|
The same explorer in the dark theme, alongside its script-free output for email and print:
|
|
26
27
|
|
|
27
28
|
| Dark theme | Static outline |
|
|
28
29
|
| --- | --- |
|
|
29
|
-
|  |  |
|
|
30
31
|
|
|
31
32
|
## Features
|
|
32
33
|
|
|
@@ -34,12 +35,13 @@ The same explorer in the dark theme, alongside its script-free output for email
|
|
|
34
35
|
| --- | --- | --- |
|
|
35
36
|
| Navigation | Expandable branches, path search and lazy children | Continuous or paged records, offset or cursor navigation |
|
|
36
37
|
| Querying | Search, sibling sorting and named filters | Search, multi-column sorting, typed filters and condition groups |
|
|
37
|
-
| Columns | Resize and hide | Resize, hide, reorder, pin
|
|
38
|
-
| Selection | Single/multiple selection and hierarchical checkboxes | Single/multiple selection with stable record IDs |
|
|
39
|
-
| Presentation | Badges, details, custom cells and light/dark themes | Links, progress, wrapped text, row highlighting and light/dark themes |
|
|
40
|
-
|
|
|
38
|
+
| Columns | Resize and hide | Resize, hide, reorder, pin, fit to content and group under multi-level headers |
|
|
39
|
+
| Selection | Single/multiple selection and hierarchical checkboxes | Single/multiple selection with stable record IDs, and cell ranges with copy, paste and a fill handle |
|
|
40
|
+
| Presentation | Badges, details, custom cells and light/dark themes | Links, progress, wrapped text, row highlighting, conditional formatting and light/dark themes |
|
|
41
|
+
| Grouping and details | Nested branches and detail rows | Multi-level row groups with labelled aggregates, and expandable detail rows holding a template, HTML or a nested grid or tree |
|
|
42
|
+
| Delivery | Single HTML file, sidecar bundle or hosted data | Single HTML file, row-chunk sidecar bundle or hosted data |
|
|
41
43
|
|
|
42
|
-
Both views use virtual rows and support keyboard navigation. Reporting grids also provide grouping
|
|
44
|
+
Both views use virtual rows and support keyboard navigation. Both can mark search and filter matches with a match count and next/previous navigation ([search highlighting](docs/search-highlight.md)), and let readers switch between fitting the width, scrolling sideways and (on grids) cards, in three densities ([layout modes](docs/layout-modes.md)). Reporting grids also provide multi-level grouping with aggregates, detail rows, saved views, CSV export and row copying (see [docs/grouping.md](docs/grouping.md)). Grids and trees can open each record in a record panel: record-only fields in tabs and sections, lists, objects and nested collections, links between records, timelines, record deep links, and copy, print and export of one record, with details loaded on demand for large reports (see [docs/record-panel.md](docs/record-panel.md)). English labels are built in; Polish, German, Spanish, French and Italian packs are included.
|
|
43
45
|
|
|
44
46
|
## Installation
|
|
45
47
|
|
|
@@ -59,6 +61,8 @@ dotnet add package CanopyX.Html
|
|
|
59
61
|
|
|
60
62
|
Neither .NET package adds third-party runtime dependencies. Generating a report from C# needs no Node.js, npm or JavaScript build step.
|
|
61
63
|
|
|
64
|
+
To serve a hosted grid from your own data, add `CanopyX.Data` (server-side paging, sorting, filtering, value lists, multi-level summaries, streamed export and commits of edited rows over `IQueryable<T>` or your own provider) and, in ASP.NET Core, `CanopyX.AspNetCore` for the endpoints. See [Server-side data for .NET](docs/remote-dotnet.md).
|
|
65
|
+
|
|
62
66
|
### JavaScript
|
|
63
67
|
|
|
64
68
|
```shell
|
|
@@ -184,15 +188,63 @@ The stylesheet import uses your application's asset pipeline. For a page without
|
|
|
184
188
|
|
|
185
189
|
Module imports are safe on the server; mounting a view requires a browser. The included TypeScript declarations describe the view, data-source and event APIs.
|
|
186
190
|
|
|
191
|
+
### Enhance a table, or start from records or a URL
|
|
192
|
+
|
|
193
|
+
A page that already has an HTML table needs one call. The table's headers, rows, `data-order` and `data-search` values, row ids, caption and footer become a grid with search, filters, sorting, numbered pages and export, and the table stays the script-free fallback:
|
|
194
|
+
|
|
195
|
+
```html
|
|
196
|
+
<link rel="stylesheet" href="canopyx-grid.css">
|
|
197
|
+
<script src="canopyx-grid.js"></script>
|
|
198
|
+
<script>CanopyX.enhance("#servers", { pageLength: 10, stateSave: true });</script>
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
`CanopyX.grid(element, { data, columns })` builds the same grid from plain records with field paths and render functions, and `url` reads records from an address once or, with `serverSide`, asks it for every page. See [docs/enhance.md](docs/enhance.md) and [docs/paging.md](docs/paging.md).
|
|
202
|
+
|
|
203
|
+
### Extend it with plugins
|
|
204
|
+
|
|
205
|
+
`CanopyX.use(plugin)` adds cell renderers that columns choose by name, toolbar buttons, menu entries, export formats and event handlers to every grid and tree on the page; the `plugins` option adds them to one view. Optional features load as separate parts only when a view needs them, so serve the `canopyx-*.js` files beside the runtime (the .NET writers do). See [docs/plugins.md](docs/plugins.md).
|
|
206
|
+
|
|
207
|
+
### Edit data in a grid
|
|
208
|
+
|
|
209
|
+
Mark flat-grid columns `editable` and give them typed editors (text, number, date and time, select, toggle, lookup) and validation. Readers edit in the cells (or in the record drawer on phones) with undo and redo; changes stay marked until your callbacks or data source save them through row or batch commits, which report each row's result. CanopyX never writes data itself. See [docs/editing.md](docs/editing.md).
|
|
210
|
+
|
|
211
|
+
### Format cells by rule
|
|
212
|
+
|
|
213
|
+
`formatRules` (in .NET, `CanopyDataGridView.FormatRules`) tints cells and rows, adds icons, badges and cues, and draws data bars, colour scales and threshold bands, with conditions from the filter builder. Readers can change the rules in a rule editor, and their rules are kept in saved views. See [docs/conditional-formatting.md](docs/conditional-formatting.md).
|
|
214
|
+
|
|
215
|
+
### Show records as a calendar
|
|
216
|
+
|
|
217
|
+
Give a grid a `calendar` (in .NET, `CanopyDataGridView.Calendar`, or `grid.Calendar().Start(x => x.Starts).End(x => x.Ends)` on a typed grid) and its records show as a month, week, day, N-day, agenda or year calendar, or, with resources, a resource timeline whose resources are a CanopyX tree. The grid's search, filters, facets, saved views, record panel, linked views, live data and editing keep working on the same records; recurring events, time zones with correct DST, iCalendar export and print come with it. See [docs/calendar.md](docs/calendar.md) and [docs/resource-timeline.md](docs/resource-timeline.md).
|
|
218
|
+
|
|
219
|
+
### Link views together
|
|
220
|
+
|
|
221
|
+
A chart, a list or another grid can filter a grid or tree (`setExternalFilter`, shown as a removable chip and sent to a host source in its query) or highlight its rows (`setHighlight`), and a view with `linkEvents` reports its selection and own conditions as neutral `canopyx:linkchange` payloads. See [docs/linked-views.md](docs/linked-views.md).
|
|
222
|
+
|
|
187
223
|
### Translate the controls
|
|
188
224
|
|
|
189
|
-
Import labels from `@evotecit/canopyx/locales/pl`, `/locales/de` or `/locales/
|
|
225
|
+
Import labels from `@evotecit/canopyx/locales/pl`, `/locales/de`, `/locales/es`, `/locales/fr` or `/locales/it` and pass them as `labels` in your view definition. In C#, set the view's `Labels` to `CanopyLabels.Polish()`, `German()`, `Spanish()`, `French()` or `Italian()` before writing the page.
|
|
226
|
+
|
|
227
|
+
### Strict security policies and accessibility
|
|
228
|
+
|
|
229
|
+
CanopyX runs under a Content Security Policy without `'unsafe-inline'` or `'unsafe-eval'`: set `CanopyHtmlOptions.Nonce` in C#, or give the runtime script a nonce, and the parts the runtime loads later carry it too. It also works with Trusted Types (`trusted-types canopyx`), writes host strings as text, and escapes CSV fields that could start a spreadsheet formula. See [docs/security.md](docs/security.md). The keyboard model, ARIA roles, forced colours, reduced motion, zoom reflow and target sizes, and what the tests check, are in [docs/accessibility.md](docs/accessibility.md).
|
|
190
230
|
|
|
191
231
|
## Working with larger datasets
|
|
192
232
|
|
|
193
233
|
Virtual rows keep the rendered DOM small. Tree bundles split data into sidecar files, and hosted sources let your application fetch records as the reader navigates. Flat-grid queries filter and sort the complete dataset before paging; loading one page does not mean the rest of the results are available in the browser.
|
|
194
234
|
|
|
195
|
-
|
|
235
|
+
`CanopyX.Data` answers a hosted grid's queries on the server, so a table over millions of database rows pages, sorts, filters, groups, counts value lists and exports without loading the result into the browser, and saves the rows readers edit through a writer the host controls ([docs/remote-dotnet.md](docs/remote-dotnet.md)).
|
|
236
|
+
|
|
237
|
+
Large single-file reports need no switch for their rows: grids of more than 5,000 rows are written as compact row data that the browser decodes chunk by chunk after the first rows have painted, gzip-compressed when large (`RowData` and its `Format` choose otherwise). Views can mount only when they come into view (`MountWhenVisible`), and grid bundles load their rows from sidecar files (`SaveHtmlBundle`). See [docs/large-data.md](docs/large-data.md) for when to use which, with measured numbers.
|
|
238
|
+
|
|
239
|
+
CSV export and copying distinguish filtered results, selected records and all records. Register your own export formats, such as an Excel or PDF writer, with `CanopyX.registerExportFormat`, and they join the grid's Export menu with the same scope choice, progress and cancellation; tree grids export their visible, selected or all rows through the same writers. For application actions, connect your own callbacks to the view.
|
|
240
|
+
|
|
241
|
+
## Documentation
|
|
242
|
+
|
|
243
|
+
- [Features](docs/features.md): everything the tree and data grids do, grouped by capability.
|
|
244
|
+
- [Recipes](docs/recipes.md): short how-tos for server data, cell values, export, phones, grouping, saved views and translations.
|
|
245
|
+
- [Authoring reference](docs/authoring.md), [column layout](docs/column-layout.md), [label packs](docs/labels.md) and the [data protocol](docs/data-protocol.md).
|
|
246
|
+
- [Planned work](TODO.md): remaining capabilities, consumers and acceptance gates.
|
|
247
|
+
- [Testing and benchmarks](docs/testing.md): the required correctness loop and explicit performance measurements.
|
|
196
248
|
|
|
197
249
|
## Community and license
|
|
198
250
|
|
package/README.nuget.md
CHANGED
|
@@ -27,7 +27,7 @@ Turn application data into searchable trees, sortable tables and standalone HTML
|
|
|
27
27
|
| Presentation | Badges, details, custom cells and light/dark themes | Links, progress, wrapped text, row highlighting and light/dark themes |
|
|
28
28
|
| Delivery | Single HTML file, sidecar bundle or hosted data | Single HTML file or hosted data |
|
|
29
29
|
|
|
30
|
-
Both views use virtual rows and support keyboard navigation. Reporting grids also provide grouping, aggregates, saved views, CSV export and row copying. English labels are built in; Polish, German and
|
|
30
|
+
Both views use virtual rows and support keyboard navigation. Reporting grids also provide grouping, aggregates, saved views, CSV export and row copying. English labels are built in; Polish, German, Spanish, French and Italian packs are included.
|
|
31
31
|
|
|
32
32
|
## Installation
|
|
33
33
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@evotecit/canopyx",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Interactive tree grids and data tables with virtual rows, search, filters and offline HTML reports.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -32,6 +32,49 @@
|
|
|
32
32
|
"./reporting.js": "./CanopyX.Html/Assets/canopyx-reporting.js",
|
|
33
33
|
"./filter-editor.js": "./CanopyX.Html/Assets/canopyx-filter-editor.js",
|
|
34
34
|
"./filter-editor.css": "./CanopyX.Html/Assets/canopyx-filter-editor.css",
|
|
35
|
+
"./export.js": "./CanopyX.Html/Assets/canopyx-export.js",
|
|
36
|
+
"./history.js": "./CanopyX.Html/Assets/canopyx-history.js",
|
|
37
|
+
"./pager.js": "./CanopyX.Html/Assets/canopyx-pager.js",
|
|
38
|
+
"./pager.css": "./CanopyX.Html/Assets/canopyx-pager.css",
|
|
39
|
+
"./enhance.js": "./CanopyX.Html/Assets/canopyx-enhance.js",
|
|
40
|
+
"./data.js": "./CanopyX.Html/Assets/canopyx-data.js",
|
|
41
|
+
"./editing.js": "./CanopyX.Html/Assets/canopyx-editing.js",
|
|
42
|
+
"./editing.css": "./CanopyX.Html/Assets/canopyx-editing.css",
|
|
43
|
+
"./column-groups.js": "./CanopyX.Html/Assets/canopyx-column-groups.js",
|
|
44
|
+
"./column-groups.css": "./CanopyX.Html/Assets/canopyx-column-groups.css",
|
|
45
|
+
"./cell-range.js": "./CanopyX.Html/Assets/canopyx-cell-range.js",
|
|
46
|
+
"./cell-range.css": "./CanopyX.Html/Assets/canopyx-cell-range.css",
|
|
47
|
+
"./tree-tools.js": "./CanopyX.Html/Assets/canopyx-tree-tools.js",
|
|
48
|
+
"./tree-tools.css": "./CanopyX.Html/Assets/canopyx-tree-tools.css",
|
|
49
|
+
"./links.js": "./CanopyX.Html/Assets/canopyx-links.js",
|
|
50
|
+
"./search.js": "./CanopyX.Html/Assets/canopyx-search.js",
|
|
51
|
+
"./formatting.js": "./CanopyX.Html/Assets/canopyx-formatting.js",
|
|
52
|
+
"./formatting.css": "./CanopyX.Html/Assets/canopyx-formatting.css",
|
|
53
|
+
"./format-editor.js": "./CanopyX.Html/Assets/canopyx-format-editor.js",
|
|
54
|
+
"./format-editor.css": "./CanopyX.Html/Assets/canopyx-format-editor.css",
|
|
55
|
+
"./link.js": "./CanopyX.Html/Assets/canopyx-link.js",
|
|
56
|
+
"./link.css": "./CanopyX.Html/Assets/canopyx-link.css",
|
|
57
|
+
"./detail-rows.js": "./CanopyX.Html/Assets/canopyx-detail-rows.js",
|
|
58
|
+
"./detail-rows.css": "./CanopyX.Html/Assets/canopyx-detail-rows.css",
|
|
59
|
+
"./grouping.js": "./CanopyX.Html/Assets/canopyx-grouping.js",
|
|
60
|
+
"./grouping.css": "./CanopyX.Html/Assets/canopyx-grouping.css",
|
|
61
|
+
"./highlight.js": "./CanopyX.Html/Assets/canopyx-highlight.js",
|
|
62
|
+
"./highlight.css": "./CanopyX.Html/Assets/canopyx-highlight.css",
|
|
63
|
+
"./layouts.js": "./CanopyX.Html/Assets/canopyx-layouts.js",
|
|
64
|
+
"./layouts.css": "./CanopyX.Html/Assets/canopyx-layouts.css",
|
|
65
|
+
"./record-panel.js": "./CanopyX.Html/Assets/canopyx-record-panel.js",
|
|
66
|
+
"./record-panel.css": "./CanopyX.Html/Assets/canopyx-record-panel.css",
|
|
67
|
+
"./live.js": "./CanopyX.Html/Assets/canopyx-live.js",
|
|
68
|
+
"./live.css": "./CanopyX.Html/Assets/canopyx-live.css",
|
|
69
|
+
"./facets.js": "./CanopyX.Html/Assets/canopyx-facets.js",
|
|
70
|
+
"./facets.css": "./CanopyX.Html/Assets/canopyx-facets.css",
|
|
71
|
+
"./calendar.js": "./CanopyX.Html/Assets/canopyx-calendar.js",
|
|
72
|
+
"./calendar.css": "./CanopyX.Html/Assets/canopyx-calendar.css",
|
|
73
|
+
"./calendar-recurrence.js": "./CanopyX.Html/Assets/canopyx-calendar-recurrence.js",
|
|
74
|
+
"./calendar-edit.js": "./CanopyX.Html/Assets/canopyx-calendar-edit.js",
|
|
75
|
+
"./calendar-ics.js": "./CanopyX.Html/Assets/canopyx-calendar-ics.js",
|
|
76
|
+
"./timeline.js": "./CanopyX.Html/Assets/canopyx-timeline.js",
|
|
77
|
+
"./timeline.css": "./CanopyX.Html/Assets/canopyx-timeline.css",
|
|
35
78
|
"./locales/pl": {
|
|
36
79
|
"types": "./JavaScript/locales/pl.d.ts",
|
|
37
80
|
"import": "./JavaScript/locales/pl.mjs"
|
|
@@ -44,9 +87,19 @@
|
|
|
44
87
|
"types": "./JavaScript/locales/es.d.ts",
|
|
45
88
|
"import": "./JavaScript/locales/es.mjs"
|
|
46
89
|
},
|
|
90
|
+
"./locales/fr": {
|
|
91
|
+
"types": "./JavaScript/locales/fr.d.ts",
|
|
92
|
+
"import": "./JavaScript/locales/fr.mjs"
|
|
93
|
+
},
|
|
94
|
+
"./locales/it": {
|
|
95
|
+
"types": "./JavaScript/locales/it.d.ts",
|
|
96
|
+
"import": "./JavaScript/locales/it.mjs"
|
|
97
|
+
},
|
|
47
98
|
"./locales/pl.js": "./CanopyX.Html/Assets/canopyx-labels-pl.js",
|
|
48
99
|
"./locales/de.js": "./CanopyX.Html/Assets/canopyx-labels-de.js",
|
|
49
|
-
"./locales/es.js": "./CanopyX.Html/Assets/canopyx-labels-es.js"
|
|
100
|
+
"./locales/es.js": "./CanopyX.Html/Assets/canopyx-labels-es.js",
|
|
101
|
+
"./locales/fr.js": "./CanopyX.Html/Assets/canopyx-labels-fr.js",
|
|
102
|
+
"./locales/it.js": "./CanopyX.Html/Assets/canopyx-labels-it.js"
|
|
50
103
|
},
|
|
51
104
|
"files": [
|
|
52
105
|
"docs/images/*.png",
|
|
@@ -66,7 +119,50 @@
|
|
|
66
119
|
"CanopyX.Html/Assets/canopyx-reporting.js",
|
|
67
120
|
"CanopyX.Html/Assets/canopyx-reporting.css",
|
|
68
121
|
"CanopyX.Html/Assets/canopyx-filter-editor.js",
|
|
69
|
-
"CanopyX.Html/Assets/canopyx-filter-editor.css"
|
|
122
|
+
"CanopyX.Html/Assets/canopyx-filter-editor.css",
|
|
123
|
+
"CanopyX.Html/Assets/canopyx-export.js",
|
|
124
|
+
"CanopyX.Html/Assets/canopyx-history.js",
|
|
125
|
+
"CanopyX.Html/Assets/canopyx-pager.js",
|
|
126
|
+
"CanopyX.Html/Assets/canopyx-pager.css",
|
|
127
|
+
"CanopyX.Html/Assets/canopyx-enhance.js",
|
|
128
|
+
"CanopyX.Html/Assets/canopyx-data.js",
|
|
129
|
+
"CanopyX.Html/Assets/canopyx-editing.js",
|
|
130
|
+
"CanopyX.Html/Assets/canopyx-editing.css",
|
|
131
|
+
"CanopyX.Html/Assets/canopyx-column-groups.js",
|
|
132
|
+
"CanopyX.Html/Assets/canopyx-column-groups.css",
|
|
133
|
+
"CanopyX.Html/Assets/canopyx-cell-range.js",
|
|
134
|
+
"CanopyX.Html/Assets/canopyx-cell-range.css",
|
|
135
|
+
"CanopyX.Html/Assets/canopyx-tree-tools.js",
|
|
136
|
+
"CanopyX.Html/Assets/canopyx-tree-tools.css",
|
|
137
|
+
"CanopyX.Html/Assets/canopyx-links.js",
|
|
138
|
+
"CanopyX.Html/Assets/canopyx-search.js",
|
|
139
|
+
"CanopyX.Html/Assets/canopyx-formatting.js",
|
|
140
|
+
"CanopyX.Html/Assets/canopyx-formatting.css",
|
|
141
|
+
"CanopyX.Html/Assets/canopyx-format-editor.js",
|
|
142
|
+
"CanopyX.Html/Assets/canopyx-format-editor.css",
|
|
143
|
+
"CanopyX.Html/Assets/canopyx-link.js",
|
|
144
|
+
"CanopyX.Html/Assets/canopyx-link.css",
|
|
145
|
+
"CanopyX.Html/Assets/canopyx-detail-rows.js",
|
|
146
|
+
"CanopyX.Html/Assets/canopyx-detail-rows.css",
|
|
147
|
+
"CanopyX.Html/Assets/canopyx-grouping.js",
|
|
148
|
+
"CanopyX.Html/Assets/canopyx-grouping.css",
|
|
149
|
+
"CanopyX.Html/Assets/canopyx-highlight.js",
|
|
150
|
+
"CanopyX.Html/Assets/canopyx-highlight.css",
|
|
151
|
+
"CanopyX.Html/Assets/canopyx-layouts.js",
|
|
152
|
+
"CanopyX.Html/Assets/canopyx-layouts.css",
|
|
153
|
+
"CanopyX.Html/Assets/canopyx-record-panel.js",
|
|
154
|
+
"CanopyX.Html/Assets/canopyx-record-panel.css",
|
|
155
|
+
"CanopyX.Html/Assets/canopyx-live.js",
|
|
156
|
+
"CanopyX.Html/Assets/canopyx-live.css",
|
|
157
|
+
"CanopyX.Html/Assets/canopyx-facets.js",
|
|
158
|
+
"CanopyX.Html/Assets/canopyx-facets.css",
|
|
159
|
+
"CanopyX.Html/Assets/canopyx-calendar.js",
|
|
160
|
+
"CanopyX.Html/Assets/canopyx-calendar.css",
|
|
161
|
+
"CanopyX.Html/Assets/canopyx-calendar-recurrence.js",
|
|
162
|
+
"CanopyX.Html/Assets/canopyx-calendar-edit.js",
|
|
163
|
+
"CanopyX.Html/Assets/canopyx-calendar-ics.js",
|
|
164
|
+
"CanopyX.Html/Assets/canopyx-timeline.js",
|
|
165
|
+
"CanopyX.Html/Assets/canopyx-timeline.css"
|
|
70
166
|
],
|
|
71
167
|
"keywords": [
|
|
72
168
|
"treegrid",
|