@evotecit/canopyx 0.3.16 → 0.3.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/CanopyX.Html/Assets/canopyx-board.css +50 -0
  2. package/CanopyX.Html/Assets/canopyx-board.js +39 -0
  3. package/CanopyX.Html/Assets/canopyx-buckets.js +15 -0
  4. package/CanopyX.Html/Assets/canopyx-calculations.css +7 -0
  5. package/CanopyX.Html/Assets/canopyx-calculations.js +52 -0
  6. package/CanopyX.Html/Assets/canopyx-calendar-edit.js +3 -3
  7. package/CanopyX.Html/Assets/canopyx-calendar.css +5 -24
  8. package/CanopyX.Html/Assets/canopyx-calendar.js +14 -19
  9. package/CanopyX.Html/Assets/canopyx-cell-range.js +16 -14
  10. package/CanopyX.Html/Assets/canopyx-changes.css +6 -24
  11. package/CanopyX.Html/Assets/canopyx-changes.js +18 -15
  12. package/CanopyX.Html/Assets/canopyx-compare.css +37 -0
  13. package/CanopyX.Html/Assets/canopyx-compare.js +12 -0
  14. package/CanopyX.Html/Assets/canopyx-data.js +3 -3
  15. package/CanopyX.Html/Assets/canopyx-editing.css +2 -2
  16. package/CanopyX.Html/Assets/canopyx-editing.js +2 -2
  17. package/CanopyX.Html/Assets/canopyx-enhance.js +4 -4
  18. package/CanopyX.Html/Assets/canopyx-export.js +54 -13
  19. package/CanopyX.Html/Assets/canopyx-facets.css +14 -5
  20. package/CanopyX.Html/Assets/canopyx-facets.js +19 -15
  21. package/CanopyX.Html/Assets/canopyx-filter-editor.css +71 -85
  22. package/CanopyX.Html/Assets/canopyx-filter-editor.js +20 -16
  23. package/CanopyX.Html/Assets/canopyx-flow-checks.css +1 -1
  24. package/CanopyX.Html/Assets/canopyx-flow-checks.js +1 -1
  25. package/CanopyX.Html/Assets/canopyx-flow-dialog.css +2 -2
  26. package/CanopyX.Html/Assets/canopyx-flow-dialog.js +1 -1
  27. package/CanopyX.Html/Assets/canopyx-flow-entry.css +136 -12
  28. package/CanopyX.Html/Assets/canopyx-flow-entry.js +2 -2
  29. package/CanopyX.Html/Assets/canopyx-flow-module.mjs +2 -2
  30. package/CanopyX.Html/Assets/canopyx-format-editor.js +2 -2
  31. package/CanopyX.Html/Assets/canopyx-formatting.js +10 -9
  32. package/CanopyX.Html/Assets/canopyx-grid-module.mjs +182 -128
  33. package/CanopyX.Html/Assets/canopyx-grid.css +228 -96
  34. package/CanopyX.Html/Assets/canopyx-grid.js +182 -128
  35. package/CanopyX.Html/Assets/canopyx-grouping.css +22 -15
  36. package/CanopyX.Html/Assets/canopyx-grouping.js +24 -17
  37. package/CanopyX.Html/Assets/canopyx-interactive.css +197 -74
  38. package/CanopyX.Html/Assets/canopyx-interactive.js +38 -45
  39. package/CanopyX.Html/Assets/canopyx-labels-de.js +177 -9
  40. package/CanopyX.Html/Assets/canopyx-labels-es.js +177 -9
  41. package/CanopyX.Html/Assets/canopyx-labels-fr.js +176 -8
  42. package/CanopyX.Html/Assets/canopyx-labels-it.js +176 -8
  43. package/CanopyX.Html/Assets/canopyx-labels-pl.js +176 -8
  44. package/CanopyX.Html/Assets/canopyx-layouts.css +48 -20
  45. package/CanopyX.Html/Assets/canopyx-layouts.js +36 -14
  46. package/CanopyX.Html/Assets/canopyx-link.js +2 -2
  47. package/CanopyX.Html/Assets/canopyx-live.css +1 -3
  48. package/CanopyX.Html/Assets/canopyx-live.js +3 -3
  49. package/CanopyX.Html/Assets/canopyx-matrix.css +1 -8
  50. package/CanopyX.Html/Assets/canopyx-matrix.js +11 -11
  51. package/CanopyX.Html/Assets/canopyx-module.mjs +38 -45
  52. package/CanopyX.Html/Assets/canopyx-office-export.js +2936 -0
  53. package/CanopyX.Html/Assets/canopyx-path.css +45 -0
  54. package/CanopyX.Html/Assets/canopyx-path.js +28 -0
  55. package/CanopyX.Html/Assets/canopyx-pivot.css +75 -0
  56. package/CanopyX.Html/Assets/canopyx-pivot.js +72 -0
  57. package/CanopyX.Html/Assets/canopyx-plan.css +56 -0
  58. package/CanopyX.Html/Assets/canopyx-plan.js +67 -0
  59. package/CanopyX.Html/Assets/canopyx-presenters.js +2 -2
  60. package/CanopyX.Html/Assets/canopyx-record-panel.css +8 -7
  61. package/CanopyX.Html/Assets/canopyx-record-panel.js +15 -14
  62. package/CanopyX.Html/Assets/canopyx-reporting-module.mjs +222 -161
  63. package/CanopyX.Html/Assets/canopyx-reporting.css +240 -107
  64. package/CanopyX.Html/Assets/canopyx-reporting.js +222 -161
  65. package/CanopyX.Html/Assets/canopyx-stack.css +35 -0
  66. package/CanopyX.Html/Assets/canopyx-stack.js +24 -0
  67. package/CanopyX.Html/Assets/canopyx-time-slider.css +18 -0
  68. package/CanopyX.Html/Assets/canopyx-time-slider.js +27 -0
  69. package/CanopyX.Html/Assets/canopyx-timeline.js +6 -5
  70. package/CanopyX.Html/Assets/canopyx-tree-tools.css +36 -35
  71. package/CanopyX.Html/Assets/canopyx-tree-tools.js +15 -12
  72. package/CanopyX.Html/Assets/canopyx-ui-menu.css +41 -0
  73. package/CanopyX.Html/Assets/canopyx-ui-menu.js +64 -0
  74. package/CanopyX.Html/Assets/canopyx-ui-navigation.css +73 -0
  75. package/CanopyX.Html/Assets/canopyx-ui-navigation.js +39 -0
  76. package/CanopyX.Html/Assets/canopyx-ui-overlays.css +79 -0
  77. package/CanopyX.Html/Assets/canopyx-ui-overlays.js +42 -0
  78. package/CanopyX.Html/Assets/canopyx-ui-picker.css +12 -0
  79. package/CanopyX.Html/Assets/canopyx-ui-picker.js +6 -0
  80. package/CanopyX.Html/Assets/canopyx-ui-stepper.css +174 -0
  81. package/CanopyX.Html/Assets/canopyx-ui-stepper.js +48 -0
  82. package/CanopyX.Html/Assets/canopyx-ui-tabs.css +153 -0
  83. package/CanopyX.Html/Assets/canopyx-ui-tabs.js +47 -0
  84. package/CanopyX.Html/Assets/canopyx-values.css +5 -0
  85. package/CanopyX.Html/Assets/canopyx-values.js +13 -0
  86. package/CanopyX.Html/Assets/canopyx-view-intents.css +12 -0
  87. package/CanopyX.Html/Assets/canopyx-view-intents.js +56 -0
  88. package/CanopyX.Html/Assets/canopyx.css +197 -71
  89. package/CanopyX.Html/Assets/canopyx.js +29 -19
  90. package/JavaScript/board.d.ts +30 -0
  91. package/JavaScript/changes.d.ts +4 -1
  92. package/JavaScript/facets.d.ts +5 -3
  93. package/JavaScript/grid.d.ts +150 -16
  94. package/JavaScript/hosts.d.ts +14 -1
  95. package/JavaScript/index.d.ts +4 -2
  96. package/JavaScript/locales/de.mjs +177 -9
  97. package/JavaScript/locales/es.mjs +177 -9
  98. package/JavaScript/locales/fr.mjs +176 -8
  99. package/JavaScript/locales/it.mjs +176 -8
  100. package/JavaScript/locales/pl.mjs +176 -8
  101. package/JavaScript/matrix.d.ts +4 -1
  102. package/JavaScript/path.d.ts +33 -0
  103. package/JavaScript/pivot.d.ts +135 -0
  104. package/JavaScript/plan.d.ts +23 -0
  105. package/JavaScript/protocol.d.ts +16 -3
  106. package/JavaScript/records.d.ts +2 -0
  107. package/JavaScript/stack.d.ts +28 -0
  108. package/JavaScript/time-slider.d.ts +58 -0
  109. package/JavaScript/ui.d.ts +261 -0
  110. package/JavaScript/view-intents.d.ts +45 -0
  111. package/README.md +22 -3
  112. package/ThirdParty/OfficeIMO/LICENSE +21 -0
  113. package/ThirdParty/OfficeIMO/README.md +13 -0
  114. package/package.json +76 -3
@@ -0,0 +1,261 @@
1
+ import type { LabelName } from "./protocol.js";
2
+
3
+ /** An element, or a selector resolving to one element. Context-menu selectors are delegated instead. */
4
+ export type UiTarget = HTMLElement | string;
5
+ /** Calls made before ready wait for the lazy implementation; after readiness, queries may return synchronously. */
6
+ export type UiResult<T> = T | Promise<T>;
7
+ /** Host-owned labels override the runtime defaults. */
8
+ export type UiLabels = Partial<Record<LabelName, string>>;
9
+
10
+ /** The public wrapper is stable from creation until destruction, including while its lazy part loads. */
11
+ export interface UiController {
12
+ readonly element: HTMLElement;
13
+ /** Resolves to this same wrapper after initialization; rejects on loading failure or destruction before initialization. */
14
+ readonly ready: Promise<this>;
15
+ /** Releases this instance. Repeated calls do nothing; later method calls throw. */
16
+ destroy(): void;
17
+ }
18
+
19
+ /** A record discovered from the declarative markup, passed to navigation hooks. */
20
+ export interface UiNavigationItem {
21
+ readonly id: string;
22
+ readonly index: number;
23
+ readonly element: HTMLElement;
24
+ readonly panel?: HTMLElement;
25
+ readonly label: string;
26
+ readonly badge?: string;
27
+ readonly icon?: Node | string;
28
+ readonly disabled: boolean;
29
+ readonly optional: boolean;
30
+ readonly visited: boolean;
31
+ }
32
+
33
+ /** Loader strings are trusted host HTML and pass through CanopyX's canonical HTML/Trusted Types boundary.
34
+ * Print preparation may call loaders for inactive panels with a separate signal; return content without mutating live panels. */
35
+ export type UiContentLoader<Item extends UiNavigationItem = UiNavigationItem> =
36
+ (item: Item, signal: AbortSignal) => Node | string | null | void | Promise<Node | string | null | void>;
37
+
38
+ /** Shared deferred-panel behavior for tabs and steppers. Templates also opt a panel into deferred loading. */
39
+ export interface UiDeferredOptions<Item extends UiNavigationItem = UiNavigationItem> {
40
+ deferred?: boolean;
41
+ /** Defaults to true. False disposes deferred content on leave and loads it again on return. */
42
+ keepAlive?: boolean;
43
+ loader?: UiContentLoader<Item>;
44
+ }
45
+
46
+ /** Shared options for navigation over existing declarative markup. Host callbacks may ignore cancellation; stale results never commit. */
47
+ export interface UiNavigationOptions<Item extends UiNavigationItem = UiNavigationItem> extends UiDeferredOptions<Item> {
48
+ /** Renders an encoded icon name from the markup into a decorative node or plain text. */
49
+ renderIcon?: (icon: string, item: Partial<Item>) => Node | string | null | void;
50
+ labels?: UiLabels;
51
+ selectedIndex?: number;
52
+ /** Local item identity or zero-based index. selectedIndex takes precedence when supplied. */
53
+ selected?: string | number;
54
+ /** Returning false cancels the leave. Selection remains unchanged while this callback is pending. */
55
+ beforeChange?: (from: Item | undefined, to: Item, signal: AbortSignal) => boolean | void | Promise<boolean | void>;
56
+ }
57
+
58
+ /** Deferred settings for one tab, matched by its data-tab-id. Labels, badges and disabled state come from markup. */
59
+ export interface UiTabOptions extends UiDeferredOptions {
60
+ id: string;
61
+ }
62
+
63
+ /** Tabs over the .NET tablist/tabpanel contract. */
64
+ export interface UiTabsOptions extends UiNavigationOptions {
65
+ style?: "underline" | "pills" | "segmented" | "vertical";
66
+ overflow?: "scroll" | "menu" | "wrap";
67
+ collapse?: "picker" | "none";
68
+ activation?: "automatic" | "manual";
69
+ print?: "all" | "selected";
70
+ transition?: "none" | "fade" | "slide";
71
+ hash?: boolean;
72
+ hashHistory?: "replace" | "push";
73
+ tabs?: readonly UiTabOptions[];
74
+ /** Optional automatic progression. Manual selection stops it; reduced motion disables it.
75
+ * False disables settings emitted by the .NET builder. */
76
+ autoProgress?: false | {
77
+ /** A positive interval in milliseconds. */
78
+ interval: number;
79
+ /** Suspends the interval while hovered. Defaults to true. */
80
+ pauseOnHover?: boolean;
81
+ /** Suspends the interval while focus is inside. Defaults to true. */
82
+ pauseOnFocus?: boolean;
83
+ };
84
+ /** Enables the development warning when segmented tabs fall back to pills above five items. */
85
+ debug?: boolean;
86
+ }
87
+
88
+ /** Shared navigation methods. Selection identifies items by local identity or zero-based index. */
89
+ export interface UiNavigationController extends UiController {
90
+ select(idOrIndex: string | number): Promise<boolean>;
91
+ getSelected(): UiResult<string | null>;
92
+ /** Rediscovers the current markup and updates presentation. */
93
+ refresh(): UiResult<void>;
94
+ /** Prepares deferred print bodies without navigation. Await before window.print(); rejects on load failure or cancellation. */
95
+ preparePrint(): Promise<void>;
96
+ }
97
+ export interface UiTabsController extends UiNavigationController {}
98
+
99
+ /** Step states are presentation supplied by the host or by successful navigation and validation. */
100
+ export type UiStepState = "upcoming" | "current" | "done" | "error" | "skipped" | "disabled";
101
+ export interface UiStepItem extends UiNavigationItem {
102
+ readonly state: UiStepState;
103
+ }
104
+ export interface UiStepOptions extends UiDeferredOptions<UiStepItem> {
105
+ id: string;
106
+ }
107
+ /** A false value or a nonempty message array rejects navigation; messages render as a focused alert. */
108
+ export type UiStepValidation = boolean | readonly string[] | void;
109
+ export interface UiStepperState {
110
+ selected: string | null;
111
+ finished: boolean;
112
+ steps: Array<{ id: string; state: UiStepState; current: boolean; visited: boolean; optional: boolean }>;
113
+ }
114
+
115
+ /** A content wizard, a readable report, or a static progress header. */
116
+ export interface UiStepperOptions extends UiNavigationOptions<UiStepItem> {
117
+ mode?: "interactive" | "report" | "static";
118
+ linear?: boolean;
119
+ vertical?: "inline" | "side";
120
+ resetForwardOnBack?: boolean;
121
+ steps?: readonly UiStepOptions[];
122
+ validate?: (step: UiStepItem, signal: AbortSignal) => UiStepValidation | Promise<UiStepValidation>;
123
+ backLabel?: string;
124
+ nextLabel?: string;
125
+ finishLabel?: string;
126
+ skipLabel?: string;
127
+ saveDraftLabel?: string;
128
+ /** False omits Skip even for optional steps. */
129
+ skip?: boolean;
130
+ onSaveDraft?: (state: UiStepperState) => void;
131
+ onFinish?: (state: UiStepperState) => void;
132
+ }
133
+ export interface UiStepperController extends UiNavigationController {
134
+ next(): Promise<boolean>;
135
+ back(): Promise<boolean>;
136
+ skip(): Promise<boolean>;
137
+ finish(): Promise<boolean>;
138
+ /** Invalid transitions (including skipping a required step) return false. */
139
+ setStepState(id: string, state: UiStepState): UiResult<boolean>;
140
+ getState(): UiResult<UiStepperState>;
141
+ }
142
+
143
+ /** Positioning sides use logical start/end alignment for vertical placements. */
144
+ export type UiPlacement = "top" | "bottom" | "left" | "right" | "top-start" | "top-end" | "bottom-start" | "bottom-end";
145
+ export interface UiOverlayOpenOptions {
146
+ modal?: boolean;
147
+ /** Viewport coordinates for pointer-anchored menus. */
148
+ point?: { x: number; y: number };
149
+ }
150
+ export interface UiOverlayOptions {
151
+ trigger?: HTMLElement;
152
+ host?: HTMLElement;
153
+ placement?: UiPlacement;
154
+ dismissible?: boolean;
155
+ modal?: boolean;
156
+ initialFocus?: HTMLElement | ((element: HTMLElement) => HTMLElement | null | undefined);
157
+ focus?: boolean;
158
+ }
159
+ /** Shared open/close behavior for popovers and tooltips. */
160
+ export interface UiOverlayController extends UiController {
161
+ open(options?: UiOverlayOpenOptions): UiResult<boolean>;
162
+ close(reason?: string, restoreFocus?: boolean, force?: boolean): UiResult<boolean>;
163
+ }
164
+ export interface UiDialogOptions {
165
+ trigger?: HTMLElement;
166
+ host?: HTMLElement;
167
+ /** The container whose width selects the drawer's phone behavior. */
168
+ container?: HTMLElement;
169
+ labels?: UiLabels;
170
+ dismissible?: boolean;
171
+ initialFocus?: HTMLElement | ((element: HTMLElement) => HTMLElement | null | undefined);
172
+ }
173
+ export interface UiDrawerOptions extends UiDialogOptions {
174
+ modal?: boolean;
175
+ /** Header navigation when focus is outside an editable field. */
176
+ records?: (direction: -1 | 1) => void;
177
+ }
178
+ export interface UiDialogState { open: boolean; modal: boolean }
179
+ export interface UiDialogController extends UiOverlayController {
180
+ /** Dialog modality is fixed; drawer modality comes from its container width and factory options. */
181
+ open(): UiResult<boolean>;
182
+ refresh(): UiResult<void>;
183
+ getState(): UiResult<UiDialogState>;
184
+ }
185
+
186
+ /** Menu decorations and actions use the same item model as context menus. */
187
+ export interface UiMenuItem {
188
+ id?: string;
189
+ label?: string;
190
+ kind?: "separator" | "groupLabel" | "grouplabel" | "radio" | "checkbox";
191
+ type?: "separator" | "groupLabel" | "grouplabel" | "radio" | "checkbox";
192
+ /** Checkbox roles are selected by kind/type or by the presence of checked. */
193
+ role?: "menuitemradio";
194
+ icon?: string;
195
+ badge?: string | number;
196
+ shortcut?: string;
197
+ checked?: boolean;
198
+ disabled?: boolean;
199
+ danger?: boolean;
200
+ group?: string;
201
+ items?: readonly UiMenuItem[];
202
+ }
203
+ export interface UiMenuSelectDetail {
204
+ id: string;
205
+ item: UiMenuItem;
206
+ checked?: boolean;
207
+ element: HTMLElement;
208
+ originalEvent: Event;
209
+ }
210
+ /** Binds behavior to a menu already rendered in markup; contextMenu supplies its own item DOM. */
211
+ export interface UiMenuOptions {
212
+ trigger?: HTMLElement;
213
+ host?: HTMLElement;
214
+ label?: string;
215
+ placement?: UiPlacement;
216
+ bindTrigger?: boolean;
217
+ renderIcon?: (icon: string, item: UiMenuItem) => Node | string | null | void;
218
+ onSelect?: (item: UiMenuItem, event: Event, element: HTMLElement, detail: UiMenuSelectDetail) => void;
219
+ }
220
+ export interface UiMenuOpenOptions extends UiOverlayOpenOptions {
221
+ focus?: "first" | "last" | "none";
222
+ }
223
+ export interface UiMenuController extends UiOverlayController {
224
+ open(options?: UiMenuOpenOptions): UiResult<boolean>;
225
+ refresh(): UiResult<void>;
226
+ }
227
+ export interface UiContextMenuOptions extends UiMenuOptions {
228
+ variant?: string;
229
+ }
230
+ /** Disposes the binding and any active context menu. ready settles after the lazy binding is installed. */
231
+ export interface UiContextMenuDisposer {
232
+ (): void;
233
+ readonly ready: Promise<void>;
234
+ }
235
+
236
+ /** Mounts declarative UI under root (including root). Report/static steppers need no controller and are skipped. */
237
+ export function mountUi(root?: ParentNode): UiController[];
238
+ /** Delegates a selector, or binds one element. Inputs, links, selected text and Shift+right-click keep their native menu. */
239
+ export function contextMenu(target: UiTarget,
240
+ items: readonly UiMenuItem[] | ((event: MouseEvent | KeyboardEvent | PointerEvent, element: HTMLElement) => readonly UiMenuItem[] | null | undefined),
241
+ options?: UiContextMenuOptions): UiContextMenuDisposer;
242
+ export function tabs(target: UiTarget, options?: UiTabsOptions): UiTabsController;
243
+ export function stepper(target: UiTarget, options?: UiStepperOptions): UiStepperController;
244
+ export function dialog(target: UiTarget, options?: UiDialogOptions): UiDialogController;
245
+ export function drawer(target: UiTarget, options?: UiDrawerOptions): UiDialogController;
246
+ export function popover(target: UiTarget, options?: UiOverlayOptions): UiOverlayController;
247
+ export function tooltip(target: UiTarget, options?: UiOverlayOptions): UiOverlayController;
248
+ export function menu(target: UiTarget, options?: UiMenuOptions): UiMenuController;
249
+
250
+ /** Named UI exports shared by tree and grid/reporting entry points. */
251
+ export interface UiApi {
252
+ mountUi: typeof mountUi;
253
+ contextMenu: typeof contextMenu;
254
+ tabs: typeof tabs;
255
+ stepper: typeof stepper;
256
+ dialog: typeof dialog;
257
+ drawer: typeof drawer;
258
+ popover: typeof popover;
259
+ tooltip: typeof tooltip;
260
+ menu: typeof menu;
261
+ }
@@ -0,0 +1,45 @@
1
+ import type { AcceptedGridQuery, GridFilter, GridFilterGroup, GridGroupLevel, GridSort, GridTupleFilter } from "./grid.js";
2
+ import type { GridPivotDefinition } from "./pivot.js";
3
+
4
+ /** A data-only view proposal. Missing fields preserve the current view; empty arrays clear the corresponding setting. */
5
+ export interface GridViewIntent {
6
+ readonly protocol: "canopyx/2";
7
+ readonly type: "viewIntent";
8
+ readonly version: 1;
9
+ readonly view: string;
10
+ readonly query?: {
11
+ readonly search?: string;
12
+ /** Regex requires the target grid to enable allowRegexSearch and uses its bounded pattern grammar. */
13
+ readonly searchMode?: "substring" | "words" | "regex";
14
+ readonly sort?: readonly GridSort[];
15
+ readonly filters?: readonly GridFilter[];
16
+ readonly filterGroup?: GridFilterGroup | null;
17
+ /** Exact correlated predicates used by pivot drill-through; [] clears them. */
18
+ readonly tupleFilters?: readonly GridTupleFilter[];
19
+ readonly groupBy?: readonly GridGroupLevel[];
20
+ };
21
+ /** Visible column identities in display order. Hidden columns remain available to queries and host policy. */
22
+ readonly columns?: readonly string[];
23
+ /** A pivot definition activates/replaces the axes and values; false returns to records. Omission preserves the mode. */
24
+ readonly pivot?: GridPivotDefinition | false;
25
+ }
26
+
27
+ /** A one-use proposal preview, tied to the grid's accepted state. It never grants data or write authorization. */
28
+ export interface GridViewIntentPreview<Q extends AcceptedGridQuery = AcceptedGridQuery> {
29
+ readonly element: HTMLElement;
30
+ readonly intent: GridViewIntent;
31
+ /** Apply the captured proposal. Rejects if the grid changed, was destroyed, or this handle was already consumed. */
32
+ apply(): Promise<Q>;
33
+ cancel(): void;
34
+ }
35
+
36
+ export interface GridViewIntentApi<Q extends AcceptedGridQuery = AcceptedGridQuery> {
37
+ /** Export the accepted query and visible columns as a versioned proposal. Loads the optional part. */
38
+ getViewIntent(): Promise<GridViewIntent>;
39
+ /** Validate against actual column identities, types and capabilities; never changes the view. */
40
+ validateViewIntent(input: unknown): Promise<GridViewIntent>;
41
+ /** Render preview chips without applying the proposal. */
42
+ previewViewIntent(input: GridViewIntent, container?: HTMLElement): Promise<GridViewIntentPreview<Q>>;
43
+ /** Validate and render preview chips. The reader's Apply action or returned handle applies the proposal. */
44
+ applyViewIntent(input: GridViewIntent): Promise<GridViewIntentPreview<Q>>;
45
+ }
package/README.md CHANGED
@@ -16,21 +16,26 @@ Turn application data into searchable trees, sortable tables and standalone HTML
16
16
 
17
17
  - **File and folder explorers** with expandable branches, lazy loading, search and multi-selection.
18
18
  - **Inventory and results tables** with typed sorting, filters, column resizing and saved views.
19
+ - **Analytical reports** with calendar and numeric buckets, aggregate display modes and optional [pivot tables](docs/pivot.md), backed by inline records or one grouped hosted query. [Calculated columns](docs/calculated-columns.md) use the same bounded expression grammar in C# and the browser.
19
20
  - **HTML reports** that include their own runtime and data and can be opened from disk or a file share.
20
21
  - **Application views** backed by paged or cursor-based data sources, with selection and detail callbacks.
21
22
  - **Email and print tables** rendered from the same .NET view without JavaScript.
22
23
  - **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.
24
+ - **Boards** with lanes from a column, swimlanes, WIP limits, virtual cards and host-governed moves, sharing the grid's search, facets, views and record panel ([docs/board.md](docs/board.md)).
25
+ - **Task plans** on the resource timeline, with dependencies, milestones, critical paths, baseline comparisons and conflict-marked proposals ([docs/plan.md](docs/plan.md)).
23
26
  - **Status matrices**: a state for each pair of two sets of entities, with totals, sorting, filtering and grouping on both axes, sticky headers and both axes windowed ([docs/matrix.md](docs/matrix.md)).
24
27
  - **Change views**: a text diff (inline or side by side, word marks, folded regions, windowed rows), a change list with kind badges, folders, hashes and risk flags, and how a change reached its replicas ([docs/changes.md](docs/changes.md)).
25
28
  - **Guided flows** for setup and edit tasks: steps with typed fields, conditions as data, validation, a review page with change links, secrets that never echo, and one proposal to the host ([docs/flow.md](docs/flow.md)).
26
29
 
27
- ![File explorer in the light theme, with sizes, dates, owners and an expanded detail row](https://cdn.jsdelivr.net/npm/@evotecit/canopyx@0.3.16/docs/images/tree-grid-light.png)
30
+ ![File explorer in the light theme, with sizes, dates, owners and an expanded detail row](https://cdn.jsdelivr.net/npm/@evotecit/canopyx@0.3.18/docs/images/tree-grid-light.png)
28
31
 
29
32
  The same explorer in the dark theme, alongside its script-free output for email and print:
30
33
 
31
34
  | Dark theme | Static outline |
32
35
  | --- | --- |
33
- | ![File explorer in the dark theme](https://cdn.jsdelivr.net/npm/@evotecit/canopyx@0.3.16/docs/images/tree-grid-dark.png) | ![Static outline table](https://cdn.jsdelivr.net/npm/@evotecit/canopyx@0.3.16/docs/images/static-outline.png) |
36
+ | ![File explorer in the dark theme](https://cdn.jsdelivr.net/npm/@evotecit/canopyx@0.3.18/docs/images/tree-grid-dark.png) | ![Static outline table](https://cdn.jsdelivr.net/npm/@evotecit/canopyx@0.3.18/docs/images/static-outline.png) |
37
+
38
+ Path and stack views explain explicit host-supplied chains and ordered layers over existing records. Matrix and propagation views replay supplied snapshots with manual stepping, play/pause, and reduced-motion support. Each ships as an optional part with typed C# authoring and script-free static output. See [paths](docs/path.md), [stacks](docs/stack.md), and [snapshot playback](docs/time-slider.md).
34
39
 
35
40
  ## Features
36
41
 
@@ -44,7 +49,7 @@ The same explorer in the dark theme, alongside its script-free output for email
44
49
  | 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 |
45
50
  | Delivery | Single HTML file, sidecar bundle or hosted data | Single HTML file, row-chunk sidecar bundle or hosted data |
46
51
 
47
- 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.
52
+ 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)). Optional offline Excel/PDF formats and default script-free printing use the same captured scope ([export formats](docs/authoring.md#export-formats)). 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.
48
53
 
49
54
  CanopyX reads the shared `--hfx-*` design roles for colours, fonts, radii and density, and includes standalone defaults. Use `data-hfx-style` and `data-hfx-mode` on a containing element to theme a page; `data-hfx-density="compact"` selects 32px rows and `"comfortable"` selects 40px rows. See [theming](docs/architecture.md#theming) for custom roles and the migration from `--cx-*` colour variables.
50
55
 
@@ -215,6 +220,19 @@ A page that already has an HTML table needs one call. The table's headers, rows,
215
220
 
216
221
  `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).
217
222
 
223
+ ### Build navigation and overlays
224
+
225
+ Use standalone tabs, steppers, dialogs, drawers, popovers, tooltips and menus with the same runtime. They load through its optional-parts API and work without a data view or jQuery. `CanopyX.contextMenu(elementOrSelector, items)` also adds actions to an ordinary page element. The `CanopyX.Html.Ui` builders write the accessible markup from .NET. See [UI primitives](docs/ui-primitives.md) for assets, callbacks, keyboard behavior and examples.
226
+ ### Compare datasets and preview view changes
227
+
228
+ `CanopyDatasetComparer.Compare` joins two complete keyed snapshots into one grid, with added/removed/changed rows,
229
+ before → after cells, column counts and an Only changes switch. `CanopyX.Data` can read the two host queries;
230
+ `CanopyStaticHtml.RenderComparison` writes the email fallback. See [dataset comparison](docs/dataset-compare.md).
231
+
232
+ With `viewIntents: true`, `await grid.applyViewIntent(state)` validates a versioned JSON proposal and previews it as
233
+ chips before the reader applies it. The host supplies the proposal and governs access; CanopyX makes no model calls.
234
+ See [view intents](docs/view-intents.md).
235
+
218
236
  ### Edit data in a grid
219
237
 
220
238
  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).
@@ -254,6 +272,7 @@ CSV export and copying distinguish filtered results, selected records and all re
254
272
  - [Features](docs/features.md): everything the tree and data grids do, grouped by capability.
255
273
  - [Recipes](docs/recipes.md): short how-tos for server data, cell values, export, phones, grouping, saved views and translations.
256
274
  - [Authoring reference](docs/authoring.md), [column layout](docs/column-layout.md), [label packs](docs/labels.md) and the [data protocol](docs/data-protocol.md).
275
+ - [Dataset comparison](docs/dataset-compare.md) and [validated view intents](docs/view-intents.md).
257
276
  - [Planned work](TODO.md): remaining capabilities, consumers and acceptance gates.
258
277
  - [Testing and benchmarks](docs/testing.md): the required correctness loop and explicit performance measurements.
259
278
 
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Evotec
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,13 @@
1
+ # OfficeIMO browser document writers
2
+
3
+ `officeimo-canopyx.js` is the unmodified standalone CanopyX integration from `@evotecit/officeimo` 0.1.3, published under the MIT license. `LICENSE` preserves its license and copyright notice.
4
+
5
+ The source is [the published npm archive](https://registry.npmjs.org/@evotecit/officeimo/-/officeimo-0.1.3.tgz), file `package/bundles/officeimo-canopyx.js`. The archive integrity is `sha512-zYFbU9P/9svr5Jp8dpu3EJZradQ5nipk/+JC9OlI10oxaDS88eNfK9ZVAvdhnI8Y+hoT9FTlc2eUL3u7zW7OXA==`.
6
+
7
+ The asset assembler includes this source only in the optional `office-export` part. Base runtime files contain the format descriptors and lazy loader, without the document engines. An offline page embeds the inert part only when its view declares XLSX or PDF.
8
+
9
+ Document-engine changes belong in OfficeIMO. Refresh this source from a published package after validating the archive integrity, preserve the license, regenerate assets, and run actual XLSX/PDF consumer checks. Do not patch the copied bundle.
10
+
11
+ The published writer does not preserve pivot semantics. Pivot XLSX/PDF export is not supported yet: the menu omits those formats while a pivot is active, and `exportAs` rejects an explicit `pivot: true` request. Pivot capture, print and host delivery remain available. The containing writer and real-producer artifact qualification are tracked in [OfficeIMO #3202](https://github.com/EvotecIT/OfficeIMO/pull/3202).
12
+
13
+ For ordinary PDFs, the integration bridge explicitly enables cell wrapping so default screen widths can fit the printed page without rejecting or losing text, dates or numbers. This temporary policy stays outside the unmodified vendored writer; adopt the canonical default-sizing fix with the next qualified published bundle. XLSX retains the captured width and wrapping policy.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@evotecit/canopyx",
3
- "version": "0.3.16",
3
+ "version": "0.3.18",
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",
@@ -10,6 +10,10 @@
10
10
  },
11
11
  "types": "./JavaScript/index.d.ts",
12
12
  "exports": {
13
+ "./compare.js": "./CanopyX.Html/Assets/canopyx-compare.js",
14
+ "./compare.css": "./CanopyX.Html/Assets/canopyx-compare.css",
15
+ "./view-intents.js": "./CanopyX.Html/Assets/canopyx-view-intents.js",
16
+ "./view-intents.css": "./CanopyX.Html/Assets/canopyx-view-intents.css",
13
17
  ".": {
14
18
  "types": "./JavaScript/index.d.ts",
15
19
  "import": "./CanopyX.Html/Assets/canopyx-module.mjs"
@@ -40,6 +44,7 @@
40
44
  "./filter-editor.js": "./CanopyX.Html/Assets/canopyx-filter-editor.js",
41
45
  "./filter-editor.css": "./CanopyX.Html/Assets/canopyx-filter-editor.css",
42
46
  "./export.js": "./CanopyX.Html/Assets/canopyx-export.js",
47
+ "./office-export.js": "./CanopyX.Html/Assets/canopyx-office-export.js",
43
48
  "./history.js": "./CanopyX.Html/Assets/canopyx-history.js",
44
49
  "./grid-options.js": "./CanopyX.Html/Assets/canopyx-grid-options.js",
45
50
  "./grid-options.css": "./CanopyX.Html/Assets/canopyx-grid-options.css",
@@ -75,6 +80,13 @@
75
80
  "./detail-rows.css": "./CanopyX.Html/Assets/canopyx-detail-rows.css",
76
81
  "./grouping.js": "./CanopyX.Html/Assets/canopyx-grouping.js",
77
82
  "./grouping.css": "./CanopyX.Html/Assets/canopyx-grouping.css",
83
+ "./buckets.js": "./CanopyX.Html/Assets/canopyx-buckets.js",
84
+ "./values.js": "./CanopyX.Html/Assets/canopyx-values.js",
85
+ "./values.css": "./CanopyX.Html/Assets/canopyx-values.css",
86
+ "./pivot.js": "./CanopyX.Html/Assets/canopyx-pivot.js",
87
+ "./pivot.css": "./CanopyX.Html/Assets/canopyx-pivot.css",
88
+ "./calculations.js": "./CanopyX.Html/Assets/canopyx-calculations.js",
89
+ "./calculations.css": "./CanopyX.Html/Assets/canopyx-calculations.css",
78
90
  "./highlight.js": "./CanopyX.Html/Assets/canopyx-highlight.js",
79
91
  "./highlight.css": "./CanopyX.Html/Assets/canopyx-highlight.css",
80
92
  "./layouts.js": "./CanopyX.Html/Assets/canopyx-layouts.js",
@@ -92,6 +104,18 @@
92
104
  "./calendar-ics.js": "./CanopyX.Html/Assets/canopyx-calendar-ics.js",
93
105
  "./timeline.js": "./CanopyX.Html/Assets/canopyx-timeline.js",
94
106
  "./timeline.css": "./CanopyX.Html/Assets/canopyx-timeline.css",
107
+ "./ui-overlays.js": "./CanopyX.Html/Assets/canopyx-ui-overlays.js",
108
+ "./ui-overlays.css": "./CanopyX.Html/Assets/canopyx-ui-overlays.css",
109
+ "./ui-menu.js": "./CanopyX.Html/Assets/canopyx-ui-menu.js",
110
+ "./ui-menu.css": "./CanopyX.Html/Assets/canopyx-ui-menu.css",
111
+ "./ui-picker.js": "./CanopyX.Html/Assets/canopyx-ui-picker.js",
112
+ "./ui-picker.css": "./CanopyX.Html/Assets/canopyx-ui-picker.css",
113
+ "./ui-navigation.js": "./CanopyX.Html/Assets/canopyx-ui-navigation.js",
114
+ "./ui-navigation.css": "./CanopyX.Html/Assets/canopyx-ui-navigation.css",
115
+ "./ui-tabs.js": "./CanopyX.Html/Assets/canopyx-ui-tabs.js",
116
+ "./ui-tabs.css": "./CanopyX.Html/Assets/canopyx-ui-tabs.css",
117
+ "./ui-stepper.js": "./CanopyX.Html/Assets/canopyx-ui-stepper.js",
118
+ "./ui-stepper.css": "./CanopyX.Html/Assets/canopyx-ui-stepper.css",
95
119
  "./locales/pl": {
96
120
  "types": "./JavaScript/locales/pl.d.ts",
97
121
  "import": "./JavaScript/locales/pl.mjs"
@@ -116,9 +140,26 @@
116
140
  "./locales/de.js": "./CanopyX.Html/Assets/canopyx-labels-de.js",
117
141
  "./locales/es.js": "./CanopyX.Html/Assets/canopyx-labels-es.js",
118
142
  "./locales/fr.js": "./CanopyX.Html/Assets/canopyx-labels-fr.js",
119
- "./locales/it.js": "./CanopyX.Html/Assets/canopyx-labels-it.js"
143
+ "./locales/it.js": "./CanopyX.Html/Assets/canopyx-labels-it.js",
144
+ "./board.js": "./CanopyX.Html/Assets/canopyx-board.js",
145
+ "./plan.js": "./CanopyX.Html/Assets/canopyx-plan.js",
146
+ "./board.css": "./CanopyX.Html/Assets/canopyx-board.css",
147
+ "./plan.css": "./CanopyX.Html/Assets/canopyx-plan.css",
148
+ "./path.js": "./CanopyX.Html/Assets/canopyx-path.js",
149
+ "./path.css": "./CanopyX.Html/Assets/canopyx-path.css",
150
+ "./stack.js": "./CanopyX.Html/Assets/canopyx-stack.js",
151
+ "./stack.css": "./CanopyX.Html/Assets/canopyx-stack.css",
152
+ "./time-slider.js": "./CanopyX.Html/Assets/canopyx-time-slider.js",
153
+ "./time-slider.css": "./CanopyX.Html/Assets/canopyx-time-slider.css"
120
154
  },
121
155
  "files": [
156
+ "CanopyX.Html/Assets/canopyx-office-export.js",
157
+ "ThirdParty/OfficeIMO/LICENSE",
158
+ "ThirdParty/OfficeIMO/README.md",
159
+ "CanopyX.Html/Assets/canopyx-compare.js",
160
+ "CanopyX.Html/Assets/canopyx-compare.css",
161
+ "CanopyX.Html/Assets/canopyx-view-intents.js",
162
+ "CanopyX.Html/Assets/canopyx-view-intents.css",
122
163
  "docs/images/*.png",
123
164
  "JavaScript/*.d.ts",
124
165
  "JavaScript/locales/*.d.ts",
@@ -179,6 +220,13 @@
179
220
  "CanopyX.Html/Assets/canopyx-detail-rows.css",
180
221
  "CanopyX.Html/Assets/canopyx-grouping.js",
181
222
  "CanopyX.Html/Assets/canopyx-grouping.css",
223
+ "CanopyX.Html/Assets/canopyx-buckets.js",
224
+ "CanopyX.Html/Assets/canopyx-values.js",
225
+ "CanopyX.Html/Assets/canopyx-values.css",
226
+ "CanopyX.Html/Assets/canopyx-pivot.js",
227
+ "CanopyX.Html/Assets/canopyx-pivot.css",
228
+ "CanopyX.Html/Assets/canopyx-calculations.js",
229
+ "CanopyX.Html/Assets/canopyx-calculations.css",
182
230
  "CanopyX.Html/Assets/canopyx-highlight.js",
183
231
  "CanopyX.Html/Assets/canopyx-highlight.css",
184
232
  "CanopyX.Html/Assets/canopyx-layouts.js",
@@ -195,7 +243,32 @@
195
243
  "CanopyX.Html/Assets/canopyx-calendar-edit.js",
196
244
  "CanopyX.Html/Assets/canopyx-calendar-ics.js",
197
245
  "CanopyX.Html/Assets/canopyx-timeline.js",
198
- "CanopyX.Html/Assets/canopyx-timeline.css"
246
+ "CanopyX.Html/Assets/canopyx-timeline.css",
247
+ "CanopyX.Html/Assets/canopyx-ui-overlays.js",
248
+ "CanopyX.Html/Assets/canopyx-ui-overlays.css",
249
+ "CanopyX.Html/Assets/canopyx-ui-menu.js",
250
+ "CanopyX.Html/Assets/canopyx-ui-menu.css",
251
+ "CanopyX.Html/Assets/canopyx-ui-picker.js",
252
+ "CanopyX.Html/Assets/canopyx-ui-picker.css",
253
+ "CanopyX.Html/Assets/canopyx-ui-navigation.js",
254
+ "CanopyX.Html/Assets/canopyx-ui-navigation.css",
255
+ "CanopyX.Html/Assets/canopyx-ui-tabs.js",
256
+ "CanopyX.Html/Assets/canopyx-ui-tabs.css",
257
+ "CanopyX.Html/Assets/canopyx-ui-stepper.js",
258
+ "CanopyX.Html/Assets/canopyx-ui-stepper.css",
259
+ "CanopyX.Html/Assets/canopyx-board.js",
260
+ "CanopyX.Html/Assets/canopyx-board.css",
261
+ "CanopyX.Html/Assets/canopyx-plan.js",
262
+ "CanopyX.Html/Assets/canopyx-plan.css",
263
+ "CanopyX.Html/Assets/canopyx-path.js",
264
+ "CanopyX.Html/Assets/canopyx-path.css",
265
+ "JavaScript/path.d.ts",
266
+ "CanopyX.Html/Assets/canopyx-stack.js",
267
+ "CanopyX.Html/Assets/canopyx-stack.css",
268
+ "JavaScript/stack.d.ts",
269
+ "CanopyX.Html/Assets/canopyx-time-slider.js",
270
+ "CanopyX.Html/Assets/canopyx-time-slider.css",
271
+ "JavaScript/time-slider.d.ts"
199
272
  ],
200
273
  "keywords": [
201
274
  "forms",