@vertigis/workflow 5.48.2 → 5.50.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.
Files changed (180) hide show
  1. package/Collections.d.ts +27 -27
  2. package/Collections.js +1 -1
  3. package/EnumUtils.d.ts +5 -5
  4. package/EnumUtils.js +1 -1
  5. package/Errors.d.ts +27 -27
  6. package/Hooks.d.ts +2 -2
  7. package/IActivityHandler.d.ts +14 -14
  8. package/LanguageStringUtils.js +1 -1
  9. package/ProgramInspectorFacility.d.ts +1 -1
  10. package/ProgramInspectorFacility.js +1 -1
  11. package/Task.d.ts +3 -3
  12. package/Task.js +1 -1
  13. package/TemplateUtils.d.ts +2 -2
  14. package/Validation.d.ts +10 -1
  15. package/Validation.js +1 -1
  16. package/activities/app/GetApplicationData.d.ts +1 -1
  17. package/activities/app/GetApplicationData.js +1 -1
  18. package/activities/app/RemoveApplicationData.d.ts +1 -1
  19. package/activities/app/RemoveApplicationData.js +1 -1
  20. package/activities/app/SetApplicationData.d.ts +1 -1
  21. package/activities/app/SetApplicationData.js +1 -1
  22. package/activities/arcgis/AddFeatures.d.ts +7 -4
  23. package/activities/arcgis/AddFeatures.js +1 -1
  24. package/activities/arcgis/AreaEngineTask.d.ts +1 -1
  25. package/activities/arcgis/AreaEngineTask.js +1 -1
  26. package/activities/arcgis/BufferEngineTask.d.ts +1 -1
  27. package/activities/arcgis/BufferEngineTask.js +1 -1
  28. package/activities/arcgis/CastGeometry.d.ts +4 -4
  29. package/activities/arcgis/CompareGeometries.d.ts +1 -1
  30. package/activities/arcgis/CompareGeometries.js +1 -1
  31. package/activities/arcgis/DeleteFeatures.d.ts +7 -3
  32. package/activities/arcgis/DeleteFeatures.js +1 -1
  33. package/activities/arcgis/DifferenceEngineTask.d.ts +1 -1
  34. package/activities/arcgis/DifferenceEngineTask.js +1 -1
  35. package/activities/arcgis/FlipEngineTask.d.ts +1 -1
  36. package/activities/arcgis/FlipEngineTask.js +1 -1
  37. package/activities/arcgis/GenerateArcGisToken.d.ts +2 -2
  38. package/activities/arcgis/GeoprocessingAsync.d.ts +2 -2
  39. package/activities/arcgis/GetAttributeValue.d.ts +1 -0
  40. package/activities/arcgis/GetAttributeValues.d.ts +1 -0
  41. package/activities/arcgis/GetCurrentPosition.d.ts +28 -28
  42. package/activities/arcgis/GetFeatureGeometries.d.ts +2 -2
  43. package/activities/arcgis/GetFeatureSetExtent.d.ts +2 -2
  44. package/activities/arcgis/GetFormElementItemsFromFeatures.d.ts +2 -2
  45. package/activities/arcgis/GetFormElementItemsFromFeatures.js +1 -1
  46. package/activities/arcgis/GetGeometryExtent.d.ts +2 -2
  47. package/activities/arcgis/LengthEngineTask.d.ts +1 -1
  48. package/activities/arcgis/LengthEngineTask.js +1 -1
  49. package/activities/arcgis/MapProvider.d.ts +92 -92
  50. package/activities/arcgis/MapProvider.js +1 -1
  51. package/activities/arcgis/NearestCoordinateEngineTask.d.ts +6 -6
  52. package/activities/arcgis/NearestVertexEngineTask.d.ts +6 -6
  53. package/activities/arcgis/NearestVerticesEngineTask.d.ts +6 -6
  54. package/activities/arcgis/ProjectServiceTask.js +1 -1
  55. package/activities/arcgis/ResetLayerDefinitionExpression.d.ts +2 -2
  56. package/activities/arcgis/RunPrint.d.ts +2 -2
  57. package/activities/arcgis/RunPrint.js +1 -1
  58. package/activities/arcgis/RunReport.js +1 -1
  59. package/activities/arcgis/RunWorkflow.d.ts +4 -4
  60. package/activities/arcgis/RunWorkflow.js +1 -1
  61. package/activities/arcgis/SetImageryLayerOptions.d.ts +2 -2
  62. package/activities/arcgis/SetLayerDefinitionExpression.d.ts +2 -2
  63. package/activities/arcgis/SetLayerProperty.d.ts +2 -2
  64. package/activities/arcgis/SetLayerVisibility.d.ts +2 -2
  65. package/activities/arcgis/SetViewExtent.d.ts +4 -4
  66. package/activities/arcgis/SetViewpoint.d.ts +2 -2
  67. package/activities/arcgis/TypeChecking.d.ts +3 -3
  68. package/activities/arcgis/UpdateFeatures.d.ts +6 -3
  69. package/activities/arcgis/UpdateFeatures.js +1 -1
  70. package/activities/arcgis/libs/arcGisRestApi.d.ts +4 -4
  71. package/activities/arcgis/libs/shared.d.ts +9 -0
  72. package/activities/arcgis/libs/shared.js +1 -0
  73. package/activities/arcgis/printing.d.ts +14 -14
  74. package/activities/arcgis/runUtils.d.ts +2 -2
  75. package/activities/arcgis/runUtils.js +1 -1
  76. package/activities/arcgis/shared.d.ts +9 -2
  77. package/activities/arcgis/shared.js +1 -1
  78. package/activities/core/CalculateDate.d.ts +1 -1
  79. package/activities/core/CalculateDate.js +1 -1
  80. package/activities/core/ChannelProvider.d.ts +42 -42
  81. package/activities/core/ChannelProvider.js +1 -1
  82. package/activities/core/ForEach.d.ts +4 -4
  83. package/activities/core/FormatDate.d.ts +21 -21
  84. package/activities/core/FormatDate.js +1 -1
  85. package/activities/core/GetFirstItem.d.ts +1 -0
  86. package/activities/core/GetItemAtIndex.d.ts +1 -0
  87. package/activities/core/GetLastItem.d.ts +1 -0
  88. package/activities/core/GetWorkflowInputs.d.ts +6 -2
  89. package/activities/core/Log.d.ts +1 -1
  90. package/activities/core/Log.js +1 -1
  91. package/activities/core/Loop.d.ts +2 -2
  92. package/activities/core/ParseJson.d.ts +1 -0
  93. package/activities/core/WebRequest.d.ts +2 -2
  94. package/activities/csv/ParseCsv.d.ts +1 -0
  95. package/activities/essentials/GetEssentialsSite.d.ts +2 -2
  96. package/activities/essentials/RunEssentialsWorkflow.d.ts +2 -2
  97. package/activities/essentials/RunEssentialsWorkflow.js +1 -1
  98. package/activities/forms/DisplayForm.d.ts +6 -6
  99. package/activities/forms/DisplayForm.js +1 -1
  100. package/activities/forms/FormActor.d.ts +22 -22
  101. package/activities/forms/FormRenderer.d.ts +2 -2
  102. package/activities/forms/FormRenderer.js +1 -1
  103. package/activities/forms/GetFormElementItemsFromCollection.d.ts +7 -7
  104. package/activities/forms/GetFormElementItemsFromCollection.js +1 -1
  105. package/activities/forms/SetFormElementProperty.d.ts +1 -1
  106. package/activities/math/Max.d.ts +1 -1
  107. package/activities/math/Max.js +1 -1
  108. package/activities/math/Min.d.ts +1 -1
  109. package/activities/math/Min.js +1 -1
  110. package/activities/server/RunApplication.d.ts +2 -2
  111. package/activities/server/RunPython.d.ts +4 -4
  112. package/activities/ui/DialogContent.d.ts +6 -6
  113. package/activities/ui/DialogProvider.d.ts +5 -5
  114. package/activities/ui/DialogProvider.js +1 -1
  115. package/definition/ActivityInput.d.ts +6 -6
  116. package/definition/ProgramInspector.d.ts +118 -118
  117. package/definition/ProgramInspector.js +1 -1
  118. package/definition/Reference.d.ts +2 -2
  119. package/definition/Resource.d.ts +15 -15
  120. package/definition/Transition.d.ts +4 -4
  121. package/diagnostics/ConsoleDebugLogger.d.ts +2 -2
  122. package/diagnostics/ConsoleDebugLogger.js +1 -1
  123. package/execution/ActivityContext.d.ts +35 -35
  124. package/execution/ActivityContext.js +1 -1
  125. package/execution/ActivityContextProxy.d.ts +7 -7
  126. package/execution/ActivityContextProxy.js +1 -1
  127. package/execution/AmbientState.d.ts +29 -29
  128. package/execution/AmbientState.js +1 -1
  129. package/execution/AmbientStateProxy.d.ts +10 -10
  130. package/execution/AmbientStateProxy.js +1 -1
  131. package/execution/AsyncContext.d.ts +1 -1
  132. package/execution/AsyncContext.js +1 -1
  133. package/execution/Engine.d.ts +27 -28
  134. package/execution/Engine.js +1 -1
  135. package/execution/IDebugSession.d.ts +10 -10
  136. package/execution/MonikerFrame.d.ts +2 -2
  137. package/execution/MonikerFrame.js +1 -1
  138. package/execution/Proxy.d.ts +1 -1
  139. package/execution/Proxy.js +1 -1
  140. package/execution/StepContext.d.ts +1 -1
  141. package/execution/StepContext.js +1 -1
  142. package/execution/TransitionContext.d.ts +1 -1
  143. package/execution/TransitionContext.js +1 -1
  144. package/forms/ExclusiveTimer.d.ts +2 -2
  145. package/forms/ExclusiveTimer.js +1 -1
  146. package/forms/FormComponent.d.ts +7 -7
  147. package/forms/FormComponent.js +1 -1
  148. package/forms/FormDefinition.d.ts +50 -42
  149. package/forms/FormHost.d.ts +161 -146
  150. package/forms/FormHost.js +1 -1
  151. package/forms/FormPresenterHost.d.ts +42 -42
  152. package/forms/MutuallyExclusiveSectionGroup.d.ts +6 -6
  153. package/forms/MutuallyExclusiveSectionGroup.js +1 -1
  154. package/forms/NumberParser.d.ts +2 -2
  155. package/forms/branding/WorkflowColor.d.ts +5 -5
  156. package/forms/branding/WorkflowColor.js +1 -1
  157. package/forms/components/AutoComplete.js +1 -1
  158. package/forms/components/Button.js +1 -1
  159. package/forms/components/DateTimePicker.js +1 -1
  160. package/forms/components/Form.js +1 -1
  161. package/forms/components/FormLabelNumberField.d.ts +4 -4
  162. package/forms/components/GeometryPickerListItem.d.ts +4 -4
  163. package/forms/components/ItemPicker.js +1 -1
  164. package/forms/components/NumberRangeSlider.js +1 -1
  165. package/forms/components/NumberSlider.js +1 -1
  166. package/forms/components/Scanner.js +1 -1
  167. package/forms/components/SignatureDialog.d.ts +2 -2
  168. package/forms/components/SketchDialog.d.ts +5 -5
  169. package/forms/components/common.js +1 -1
  170. package/forms/dateUtilities.d.ts +2 -2
  171. package/forms/elements/types.d.ts +2 -2
  172. package/forms/index.d.ts +2 -2
  173. package/forms/numberFormatter.d.ts +8 -8
  174. package/forms/numberUtilities.d.ts +1 -1
  175. package/forms/utils.d.ts +6 -12
  176. package/libs/version.d.ts +1 -1
  177. package/libs/version.js +1 -1
  178. package/package.json +1 -1
  179. package/ui/UIService.d.ts +2 -2
  180. package/ui/UIService.js +1 -1
@@ -32,33 +32,54 @@ interface LastFocusInfo {
32
32
  }
33
33
  /** Exposes functionality for driving a form. */
34
34
  export declare abstract class FormHost implements FormPresenterHost {
35
- /** Indicates the overall state of the form. */
36
- form: defs.Form;
37
- deriveLocale(): string;
35
+ /** The DOM container node. */
36
+ container: HTMLElement | undefined;
37
+ /** Indicates if the form is a custom form. */
38
+ custom: boolean;
39
+ /** Indicates if the form should be dismissed. */
40
+ dismiss: boolean;
41
+ /** Indicates if the form is enabled. */
42
+ enabled: boolean;
38
43
  /** Indicates all errors to be assigned. */
39
44
  errors: Record<string, defs.Text | undefined>;
45
+ /** Indicates the overall state of the form. */
46
+ form: defs.Form;
40
47
  /** Indicates any reference information relevant to components. */
41
48
  refs: Record<string, FormComponent | undefined>;
42
- /** Indicates if the form is enabled. */
43
- enabled: boolean;
44
49
  /** Indicates if the form is visible. */
45
50
  visible: boolean;
46
- /** Indicates if the form should be dismissed. */
47
- dismiss: boolean;
48
- /** Indicates if the form is a custom form. */
49
- custom: boolean;
50
- /** The DOM container node. */
51
- container: HTMLElement | undefined;
52
- /** The next event index. */
53
- protected eventIndex: number;
54
- /** The event queue. */
55
- protected eventQueue: defs.Event[];
56
51
  /**
57
52
  * We keep track of the outermost DOM element for each form element here
58
53
  * so that when any DOM element gains focus in the form we can determine which element
59
54
  * it belongs to. This helps with deciding where to move focus to when validation fails.
60
55
  */
61
56
  protected domContainers: Record<string, HTMLElement>;
57
+ /** The next event index. */
58
+ protected eventIndex: number;
59
+ /** The event queue. */
60
+ protected eventQueue: defs.Event[];
61
+ /** Indicates the focus observer. */
62
+ protected focusObserver: ((event: FocusEvent) => void) | undefined;
63
+ /** Indicates a method to restore the last focus. */
64
+ protected lastFocus: LastFocusInfo | undefined;
65
+ /** Indicates the next element that should receive focus. */
66
+ protected nextFocus: boolean | string;
67
+ /** Indicates the next element that should receive a refresh. */
68
+ protected nextRefresh: boolean | Record<string, boolean>;
69
+ /**
70
+ * This stores values which are to be re-applied after elements have been refreshed
71
+ * due to the value of a depended-upon element changing. The values here are copied from elements prior to
72
+ * the "populate" or "suggest" handler being executed, so they may not be the same exact Items
73
+ * as next time around, but the underlying values can still be used to find the equivalent and select them.
74
+ */
75
+ protected pendingValues: Record<string, {
76
+ label?: defs.Text | undefined;
77
+ value: defs.Value;
78
+ }>;
79
+ /** Indicates the style o */
80
+ protected style: HTMLStyleElement | undefined;
81
+ /** The timer handler for idle/busy handling. */
82
+ protected timerHandle: (() => void) | undefined;
62
83
  /** The event promise, for when the consumer is waiting. */
63
84
  private eventTask;
64
85
  /**
@@ -70,56 +91,99 @@ export declare abstract class FormHost implements FormPresenterHost {
70
91
  */
71
92
  private mutuallyExclusiveSections;
72
93
  private resolveEvent;
73
- /** The timer handler for idle/busy handling. */
74
- protected timerHandle: (() => void) | undefined;
75
- /** Indicates a method to restore the last focus. */
76
- protected lastFocus: LastFocusInfo | undefined;
77
- /** Indicates the next element that should receive focus. */
78
- protected nextFocus: boolean | string;
79
- /** Indicates the next element that should receive a refresh. */
80
- protected nextRefresh: boolean | Record<string, boolean>;
81
- /** Indicates the focus observer. */
82
- protected focusObserver: ((event: FocusEvent) => void) | undefined;
83
- /** Indicates the style o */
84
- protected style: HTMLStyleElement | undefined;
85
- /** Mounts the form into the DOM. */
86
- protected mount(): void;
87
- /** Removes the form from the DOM. */
88
- protected unmount(): void;
89
94
  /**
90
- * Intelligently tracks the last focus, in response to focus events within
91
- * the form container. We attempt to determine which form element `target` belongs to,
92
- * so that we can have a better idea where we are in the order of elements.
93
- *
94
- * This comes into play later when we might want to decide where to move focus
95
- * based on where we currently are.
96
- * @param target The DOM element that has just gained focus.
95
+ * This method is used to update the values of form elements that depend on another
96
+ * and have "Persist Value on Refresh" set to true.
97
97
  */
98
- protected observeFocus(target: EventTarget): void;
98
+ applyPendingValues(): void;
99
+ /** Starts the busy timer. */
100
+ busy(): void;
101
+ /** Coerces a number. */
102
+ coerceNumber(value: string, locale?: string): number;
103
+ /** Dequeues the next event (used by observe()). */
104
+ dequeue(): defs.Event | undefined;
105
+ deriveLocale(): string;
106
+ displayDialog(children: (closeDialog: () => void) => ReactNode, DialogComponent: ComponentType<any>): Promise<void>;
107
+ /** Disposes the form. */
108
+ dispose(): boolean;
109
+ /** Enqueues an event (used by publish()). */
110
+ enqueue(type: defs.EventType, event?: defs.Event): defs.Event;
111
+ /**
112
+ * Pass on an external event to the queue.
113
+ * This method is an arrow function so that the consumer can use it without an object reference.
114
+ * @param event The event to be added to the queue.
115
+ */
116
+ enqueueExternalEvent: (event: ExternalEvent) => void;
117
+ /** Finds an element. */
118
+ find(name: string | {
119
+ name: string;
120
+ } | undefined): defs.Element | undefined;
121
+ /** Finds the name of an element. */
122
+ findName(element: defs.Element | undefined): string | undefined;
99
123
  /** Focuses the form. */
100
124
  focus(): void;
101
125
  /** Focuses the form optionally focusing the initial element. */
102
126
  focus(initial: boolean): void;
103
127
  /** Focuses the form focusing the named element. */
104
128
  focus(name: string): void;
105
- /** Shows the form. */
106
- show(): boolean;
107
- private isInvalid;
108
- private getInvalidElements;
129
+ /** Formats a number. */
130
+ formatNumber(value: number, options?: FormatOptions): string;
131
+ /** Checks the form's validity. */
132
+ hasErrors(): boolean;
133
+ /**
134
+ * Checks the specified element to determine if it has a selection,
135
+ * which would justify a dependent being populated at this time.
136
+ *
137
+ * This function is only interested in _initial_ selection defined in the designer
138
+ * rather than changes made in an element's `load` event. Those are handled separately.
139
+ * @param elementName The name of the element being depended upon.
140
+ * @returns True if the element has a selection at this time.
141
+ */
142
+ hasInitialSelectionToDependOn(elementName: string): boolean;
109
143
  hasInvalidChild(element: defs.Element): boolean;
110
- /** Shows the form in a disabled state. */
111
- spin(): boolean;
112
144
  /** Hides the form in a disabled state. */
113
145
  hide(): boolean;
114
- /** Disposes the form. */
115
- dispose(): boolean;
146
+ /** Clears the busy timer. */
147
+ idle(): void;
148
+ /** Invalidates the form with a full refresh. */
149
+ invalidate(): void;
150
+ /** Invalidates the form with optionally a full refresh. */
151
+ invalidate(full: boolean): void;
152
+ /** Invalidates the form refreshing a single element. */
153
+ invalidate(name: string | undefined): void;
154
+ /** Loads the form. */
155
+ load(form?: defs.Form, template?: defs.Form): boolean;
156
+ /** Observes the form. */
157
+ observe(): Bluebird<defs.Event | undefined>;
158
+ /** Posts an event. */
159
+ post(type: defs.EventType, event?: defs.Event): void;
160
+ /** Publishes an event (used by post()). */
161
+ publish(type: defs.EventType, event?: defs.Event): defs.Event;
162
+ /** Forcefully refresh the form (use this with care). */
163
+ refresh(name?: string): void;
116
164
  /**
117
165
  * This method renders focus for just rendered elements.
118
166
  * It also moves focus to another element when `nextFocus` is the name of an element.
119
167
  */
120
168
  renderFocus(target: HTMLElement, name?: string): boolean;
169
+ /** Renders a component's state. */
170
+ renderState(name: string, type: "geometry", state?: defs.GeometryState[]): boolean;
171
+ /** Renders a component's state. */
172
+ renderState(name: string, type: "item-picker", state?: defs.ItemPickerState): boolean;
173
+ /** Renders a component's state. */
174
+ renderState(name: string, type: string, state?: object): boolean;
121
175
  /** Renders form text as plain text. */
122
176
  renderText(content: defs.Text | undefined): string;
177
+ /** Renders the form component. */
178
+ renderVisual(component: FormComponent): any;
179
+ /** Routes an event to achieve default behavior. */
180
+ route(event: defs.Event): boolean;
181
+ /** Shows the form. */
182
+ show(): boolean;
183
+ /** Shows the form in a disabled state. */
184
+ spin(): boolean;
185
+ /** Subscribes to all posted events (this does not capture enqueued events). */
186
+ subscribe(action: FormEventHandler): FormEventSubscription;
123
187
  /**
124
188
  * Translates the text. This is a bit of a no-op as we only have access to
125
189
  * the language strings in FormRenderer.
@@ -141,50 +205,37 @@ export declare abstract class FormHost implements FormPresenterHost {
141
205
  * @returns The underlying text.
142
206
  */
143
207
  translateText(content: defs.Text | undefined): string | defs.MarkdownRef | undefined;
144
- /** Renders the form component. */
145
- renderVisual(component: FormComponent): any;
146
- /** Qualifies an event with defaults. */
147
- protected qualifyDefault(event: defs.Event): string | undefined;
148
- /** Qualifies an event. */
149
- protected qualify(type: defs.EventType, event?: defs.Event): defs.Event;
150
- /** Posts an event. */
151
- post(type: defs.EventType, event?: defs.Event): void;
152
- /** Subscribes to all posted events (this does not capture enqueued events). */
153
- subscribe(action: FormEventHandler): FormEventSubscription;
154
- /** Forcefully refresh the form (use this with care). */
155
- refresh(name?: string): void;
156
- /** Invalidates the form with a full refresh. */
157
- invalidate(): void;
158
- /** Invalidates the form with optionally a full refresh. */
159
- invalidate(full: boolean): void;
160
- /** Invalidates the form refreshing a single element. */
161
- invalidate(name: string | undefined): void;
208
+ /**
209
+ * Attempts to trap the event. This is relevant during cascading behavior which affects
210
+ * other elements but afterwards.
211
+ */
212
+ trap(event: defs.Event): boolean;
162
213
  /** Updates the form if appropriate. */
163
214
  update(): void;
164
- /** Clears the busy timer. */
165
- idle(): void;
166
- /** Starts the busy timer. */
167
- busy(): void;
168
- /** Publishes an event (used by post()). */
169
- publish(type: defs.EventType, event?: defs.Event): defs.Event;
170
- /** Enqueues an event (used by publish()). */
171
- enqueue(type: defs.EventType, event?: defs.Event): defs.Event;
172
215
  /**
173
- * Pass on an external event to the queue.
174
- * This method is an arrow function so that the consumer can use it without an object reference.
175
- * @param event The event to be added to the queue.
216
+ * Collapses all neighbouring sections except the one specified.
217
+ * @param expandedSectionName The name of the mutually exclusive section to be expanded. All others in the group will be collapsed.
176
218
  */
177
- enqueueExternalEvent: (event: ExternalEvent) => void;
178
- /** Dequeues the next event (used by observe()). */
179
- dequeue(): defs.Event | undefined;
180
- /** Observes the form. */
181
- observe(): Bluebird<defs.Event | undefined>;
182
- /** Loads the form. */
183
- load(form?: defs.Form, template?: defs.Form): boolean;
184
- /** Routes an event to achieve default behavior. */
185
- route(event: defs.Event): boolean;
219
+ updateMutuallyExclusiveSections(expandedSectionName: string): void;
220
+ /**
221
+ * Cascade the form by clearing the value of any elements downstream of the specified one
222
+ * and triggering the "populate" event for any elements that depend on it directly.
223
+ * @param elementName The name of an elements which has just changed.
224
+ * @returns True if the operation was a success, false otherwise.
225
+ */
226
+ protected cascade(elementName: string): boolean;
186
227
  /** Generates a new changed event given the source event. */
187
228
  protected changed(event: defs.Event): boolean;
229
+ /** Routes a click event. */
230
+ protected click(event: defs.Event): boolean;
231
+ /** Routes a prepare event. */
232
+ protected hydrate(event: defs.Event): boolean;
233
+ /**
234
+ * Returns true if the supplied element is effectively visible (i.e. has parent
235
+ * section - if it exists - visible) as well as itself, false otherwise.
236
+ * @param element The element to be tested.
237
+ */
238
+ protected isElementEffectivelyVisible(element: defs.Element | undefined): boolean;
188
239
  /**
189
240
  * Returns true if the supplied element is considered valid, false otherwise.
190
241
  * @param element The element to be tested.
@@ -192,73 +243,44 @@ export declare abstract class FormHost implements FormPresenterHost {
192
243
  * @param result An optional object which can be passed in to capture the error status, if any.
193
244
  */
194
245
  protected isElementValid(element: defs.Element, isInvisibleValid?: boolean, result?: Partial<defs.StatusRef>): boolean;
195
- /**
196
- * Returns true if the supplied element is effectively visible (i.e. has parent
197
- * section - if it exists - visible) as well as itself, false otherwise.
198
- * @param element The element to be tested.
199
- */
200
- protected isElementEffectivelyVisible(element: defs.Element | undefined): boolean;
201
246
  /**
202
247
  * Returns true if the element has a value defined. False otherwise.
203
248
  * @param element The element to be tested.
204
249
  */
205
250
  protected isElementValueDefined(element: defs.Element | undefined): boolean;
251
+ /** Mounts the form into the DOM. */
252
+ protected mount(): void;
206
253
  /**
207
- * Attempts to trap the event. This is relevant during cascading behavior which affects
208
- * other elements but afterwards.
209
- */
210
- trap(event: defs.Event): boolean;
211
- /**
212
- * Cascade the form by clearing the value of any elements downstream of the specified one
213
- * and triggering the "populate" event for any elements that depend on it directly.
214
- * @param elementName The name of an elements which has just changed.
215
- * @returns True if the operation was a success, false otherwise.
216
- */
217
- protected cascade(elementName: string): boolean;
218
- /** Routes a click event. */
219
- protected click(event: defs.Event): boolean;
220
- /**
221
- * Checks the specified element to determine if it has a selection,
222
- * which would justify a dependent being populated at this time.
254
+ * Intelligently tracks the last focus, in response to focus events within
255
+ * the form container. We attempt to determine which form element `target` belongs to,
256
+ * so that we can have a better idea where we are in the order of elements.
223
257
  *
224
- * This function is only interested in _initial_ selection defined in the designer
225
- * rather than changes made in an element's `load` event. Those are handled separately.
226
- * @param elementName The name of the element being depended upon.
227
- * @returns True if the element has a selection at this time.
258
+ * This comes into play later when we might want to decide where to move focus
259
+ * based on where we currently are.
260
+ * @param target The DOM element that has just gained focus.
228
261
  */
229
- hasInitialSelectionToDependOn(elementName: string): boolean;
230
- /** Routes a prepare event. */
231
- protected hydrate(event: defs.Event): boolean;
262
+ protected observeFocus(target: EventTarget): void;
263
+ /** Qualifies an event. */
264
+ protected qualify(type: defs.EventType, event?: defs.Event): defs.Event;
265
+ /** Qualifies an event with defaults. */
266
+ protected qualifyDefault(event: defs.Event): string | undefined;
232
267
  /** Determines if the event origin is a submit button. */
233
268
  protected shouldTriggerValidation(event: defs.Event): boolean | void;
269
+ /** Routes a submit event. */
270
+ protected submit(event: defs.Event): boolean;
271
+ /** Routes a suggest event. */
272
+ protected suggest(event: defs.Event): boolean;
273
+ /** Removes the form from the DOM. */
274
+ protected unmount(): void;
234
275
  /** Routes a validate event. */
235
276
  protected validate(event: defs.Event): boolean;
236
277
  /** Verifies the element given the event. */
237
278
  protected verify(event: defs.Event): boolean;
238
- /** Routes a suggest event. */
239
- protected suggest(event: defs.Event): boolean;
240
- /** Routes a submit event. */
241
- protected submit(event: defs.Event): boolean;
242
- /** Checks the form's validity. */
243
- hasErrors(): boolean;
244
- /** Finds an element. */
245
- find(name: string | {
246
- name: string;
247
- } | undefined): defs.Element | undefined;
248
- /** Finds the name of an element. */
249
- findName(element: defs.Element | undefined): string | undefined;
250
- /** Coerces a number. */
251
- coerceNumber(value: string, locale?: string): number;
252
- /** Formats a number. */
253
- formatNumber(value: number, options?: FormatOptions): string;
254
- /** Renders a component's state. */
255
- renderState(name: string, type: "geometry", state?: defs.GeometryState[]): boolean;
256
- /** Renders a component's state. */
257
- renderState(name: string, type: "item-picker", state?: defs.ItemPickerState): boolean;
258
- /** Renders a component's state. */
259
- renderState(name: string, type: string, state?: object): boolean;
279
+ private enforceMutuallyExclusiveConstraints;
280
+ private getAllSectionElements;
281
+ private getInvalidElements;
282
+ private getMutuallyExclusiveSectionGroup;
260
283
  private getParentSection;
261
- private isSectionCollapsed;
262
284
  /**
263
285
  * This method checks if the specified element is considered before the current value of `this.lastFocus`.
264
286
  * When the form is initially loading, we focus the first visible element in the form, regardless of error state.
@@ -268,6 +290,8 @@ export declare abstract class FormHost implements FormPresenterHost {
268
290
  * @returns True if the named element is considered before the one specified in `this.lastFocus`.
269
291
  */
270
292
  private isElementPositionBeforeLastFocused;
293
+ private isInvalid;
294
+ private isSectionCollapsed;
271
295
  /**
272
296
  *
273
297
  * @param target The DOM element that was focused
@@ -278,13 +302,4 @@ export declare abstract class FormHost implements FormPresenterHost {
278
302
  * @returns
279
303
  */
280
304
  private setLastFocus;
281
- private getAllSectionElements;
282
- private getMutuallyExclusiveSectionGroup;
283
- /**
284
- * Collapses all neighbouring sections except the one specified.
285
- * @param expandedSectionName The name of the mutually exclusive section to be expanded. All others in the group will be collapsed.
286
- */
287
- updateMutuallyExclusiveSections(expandedSectionName: string): void;
288
- private enforceMutuallyExclusiveConstraints;
289
- displayDialog(children: (closeDialog: () => void) => ReactNode, DialogComponent: ComponentType<any>): Promise<void>;
290
305
  }
package/forms/FormHost.js CHANGED
@@ -1 +1 @@
1
- import Bluebird from"bluebird";import{Task}from"../Task.js";import{DEFAULT_LOCALE}from"../constants.js";import*as defs from"./FormDefinition.js";import MutuallyExclusiveSectionGroup from"./MutuallyExclusiveSectionGroup.js";import NumberParser from"./NumberParser.js";import{FormElementTypes}from"./constants.js";import{format}from"./numberFormatter.js";import*as presenter from"./presenter.js";import{isCollapsibleSection,isMutuallyExclusiveSection,isSection,sortAndFilter,text}from"./utils.js";export{defs};const guid="C0166F74-982A-464E-9FB6-9605CB7649C1:",eventName=guid+"FormEvent";function createEvent(e,t){return new CustomEvent(e,{bubbles:!1,cancelable:!1,detail:t})}function overlay(e,t){switch(typeof e){case"boolean":case"number":case"string":return e;case"object":break;default:return t}if(null===e)return t;if(e instanceof Array){let s=t;null==s&&(s=[]);let i=0;for(const t of e){const n=overlay(t,s[i]);void 0!==n&&(i<e.length?s[i]=n:s.push(n),++i)}return s}let s=t;void 0===s&&(s={});for(const t in e)s[t]=overlay(e[t],s[t]);return s}function createSubscription(e){const t=function(){return void 0!==e&&(t.active=!1,e(),!0)};return t.active=!0,t}export class FormHost{constructor(){this.form={defaults:{},elements:{}},this.errors={},this.refs={},this.enabled=!1,this.visible=!1,this.dismiss=!1,this.custom=!1,this.container=document.createElement("div"),this.eventIndex=0,this.eventQueue=[],this.domContainers={},this.mutuallyExclusiveSections={},this.nextFocus=!1,this.nextRefresh=!1,this.enqueueExternalEvent=e=>{const t={type:`external$${e.name}`,name:"header",argument:e};this.enqueue(t.type,t)}}deriveLocale(){return DEFAULT_LOCALE}mount(){const e=this.container,t=e.parentNode;null==t&&document.body.appendChild(e),this.update()}unmount(){const e=this.container,t=e.parentNode;null!=t&&t.removeChild(e)}observeFocus(e){if(this.enabled&&e instanceof HTMLElement&&(!this.lastFocus||this.lastFocus.target!==e)){let t=Object.entries(this.domContainers).filter(t=>t[1].contains(e));t.length>1&&(t=t.filter(e=>this.form.elements[e[0]].type!==FormElementTypes.SECTION));const s=t.length>0?t[0][0]:void 0;this.setLastFocus(e,s)}}focus(e){null==e&&(e=!1),!0===e&&(this.lastFocus=void 0),!1===e&&!1===(e=this.nextFocus)&&(e=!0),this.nextFocus=e,this.invalidate(!0!==e?e:void 0)}show(){const e=this.container;if(void 0===e)return!1;this.custom||void 0!==this.focusObserver||e.addEventListener("focus",this.focusObserver=e=>this.observeFocus(e.target),!0),this.enabled||(this.nextRefresh=!0,this.focus()),this.enforceMutuallyExclusiveConstraints();const t=this.errors;for(const e in t){const s=this.form.elements[e];null!=s&&(s.error=t[e],this.invalidate(e))}return this.idle(),!1!==this.nextRefresh&&(this.enabled=!0,this.visible=!0,this.mount()),this.enabled}isInvalid(e){return!!e.error&&!1!==e.visible}getInvalidElements(){return Object.keys(this.form.elements).map(e=>this.form.elements[e]).filter(this.isInvalid)}hasInvalidChild(e){for(const t in this.form.elements){const s=this.form.elements[t];if(this.isInvalid(s)&&this.getParentSection(s)===e)return!0}return!1}spin(){return void 0!==this.container&&(this.idle(),this.visible&&!this.enabled||(this.nextRefresh=!0,this.enabled=!1,this.visible=!0,this.mount()),this.visible)}hide(){return void 0!==this.container&&(this.idle(),this.visible&&(this.enabled=!1,this.visible=!1,this.unmount()),!0)}dispose(){if(!this.dismiss){this.dismiss=!0;const e=this.container;e.dispatchEvent(createEvent(eventName));let t=this.focusObserver;return void 0!==t&&(e.removeEventListener("focus",t,!0),t=void 0),this.idle(),this.unmount(),this.refs={},presenter.releaseForm(this.container),this.container=void 0,this.lastFocus=void 0,this.eventTask=void 0,!0}return!1}renderFocus(e,t){if(!(this.enabled&&e instanceof HTMLElement&&!1!==this.nextFocus))return!1;const s=this.nextFocus;if(void 0!==t){if(t===s||!0===s&&void 0===this.lastFocus)return this.nextFocus=!1,this.setLastFocus(e,t),e.focus(),!0}else{const t=this.lastFocus?.target;if(!0===s&&t instanceof HTMLElement&&e.contains(t))return this.nextFocus=!1,t.focus(),!0}return!1}renderText(e){return"string"==typeof e?e:text.isMarkdown(e)?text.markdownToText(e.markdown):""}translateText(e){return"string"==typeof e||text.isMarkdown(e)?e:text.isStatus(e)?e.status:void 0}renderVisual(e){return presenter.render(e,t=>{t&&e.props.name&&(this.domContainers[e.props.name]=t)})||presenter.renderNone(e)}qualifyDefault(e){const t=sortAndFilter(this.form.elements);for(const s in t){const i=t[s];if(null!=i&&!1!==i.visible&&i.enabled){if(i.default)return e.value=i.value,s;const t=sortAndFilter(i.items);if(null!=t)for(const i in t){const n=t[i];if(null!=n&&n.visible&&n.enabled&&n.default)return e.item=i,e.value=n.value,s}}}}qualify(e,t){if(null==t&&(t={}),"clicked"===e&&void 0===t.name&&(t.name=this.qualifyDefault(t)),t.type=e,void 0===t.routingKey){const s=t.name;t.routingKey=void 0!==s?e+"$"+s:e}return t}post(e,t){t=this.publish(e,t);const s=this.container;void 0!==s&&s.dispatchEvent(createEvent(eventName,t))}subscribe(e){let t=e;const s=this.container;if(void 0===s)return createSubscription();const i=function(){t=void 0,s.removeEventListener(eventName,n)},n=function(e){const s=e.detail;void 0!==s?Bluebird.resolve().then(function(){"function"==typeof t&&t(s)}):i()};return s.addEventListener(eventName,n),createSubscription(i)}refresh(e){if(!this.custom)if("string"==typeof e){const t=this.refs[e];presenter.refresh(t)}else this.refs={},presenter.refreshForm(this,this.container)}invalidate(e){const t=this.nextRefresh;"string"==typeof e&&!0!==t&&(!1===t?this.nextRefresh={[e]:!0}:t[e]=!0),void 0!==e&&!0!==e||(this.nextRefresh=!0),!1===e&&!1===t&&(this.nextRefresh={})}update(){const e=this.nextRefresh;if(!0===e&&(this.nextRefresh=!1,this.refresh()),"object"==typeof e){this.nextRefresh=!1;for(const t in e)!0===e[t]&&this.refresh(t)}}idle(){const e=this.timerHandle;void 0!==e&&(this.timerHandle=void 0,e())}busy(){if(void 0===this.timerHandle&&void 0!==this.container){let e=setTimeout(()=>this.spin());this.timerHandle=function(){void 0!==e&&(clearTimeout(e),e=void 0)}}}publish(e,t){return this.enabled?(t=this.enqueue(e,t),this.eventQueue.length>0&&this.spin(),t):this.qualify(e,t)}enqueue(e,t){return t=this.qualify(e,t),void 0!==this.eventTask?(this.resolveEvent(t),this.eventTask=void 0,t):(this.eventQueue.push(t),t)}dequeue(){const e=this.eventQueue;if(e.length>0){let t=this.eventIndex;const s=e[t++];return t>=e.length?e.length=this.eventIndex=0:this.eventIndex=t,s}}observe(){return Bluebird.attempt(()=>{if(void 0!==this.eventTask)return this.eventTask;const e=this.dequeue();return void 0!==e?e:this.show()?(this.eventTask=new Task(e=>{this.resolveEvent=e}),this.eventTask):void 0})}load(e,t){if(void 0===this.container)return!1;if(this.eventQueue.length=this.eventIndex=0,this.eventTask=void 0,this.errors={},this.lastFocus=void 0,this.nextFocus=!0,this.nextRefresh=!0,this.enqueue("load"),this.enqueue("prepare"),null!=e){let s={defaults:{},elements:{}};s=overlay(e,s),this.form=overlay(t,s);for(const e in this.form.elements){const t={showFilter:!1,checked:!1,enabled:!0,hoisted:!1,visible:!0,overlay:!1,default:!1,validates:!1,readOnly:!1,require:!1,autoActivate:!1};let s=this.form.elements[e];if(s=overlay(s,t),s.items)for(const e in s.items){const t={enabled:!0,checked:!1,visible:!0,default:!1,validates:!1};s.items[e]=overlay(s.items[e],t)}this.form.elements[e]=s}}return!0}route(e){switch(e.type){case"changed":return this.cascade(e.name);case"checked":return this.changed(e);case"clicked":return this.click(e);case"prepare":return this.hydrate(e);case"suggest":return this.suggest(e);case"validate":return this.verify(e);case"verify":return this.submit(e)}return!1}changed(e){return this.enqueue("changed",{name:e.name,item:e.item,value:e.value}),!0}isElementValid(e,t=!0,s={status:void 0}){return null!=e&&(s.status=void 0,text.isInvalidError(e.error)?(s.status="invalid",!1):!0!==e.require||(this.isElementEffectivelyVisible(e)?!!this.isElementValueDefined(e)||(s.status="missing",!1):t))}isElementEffectivelyVisible(e){if(null==e)return!1;const t=this.getParentSection(e);return!1!==t?.visible&&!1!==e.visible}isElementValueDefined(e){if(null==e)return!1;if(e.type===FormElementTypes.CHECKBOX)return!0;const t=e.current;if(null!=t)return!0;const s=e.value;if(null!=s&&""!==s)return!0;const i=e.items;if(null!=i)for(const e in i){const t=i[e];if(null!=t&&!0===t.checked)return!0}return!1}trap(e){switch(e.type){case"populate":case"load":case"suggest":break;default:return!1}const t=e.name,s=this.find(t);if(null==s)return!1;const i=s.dependsOn;if("string"!=typeof i)return!1;const n=this.find(i);return s.enabled=this.isElementEffectivelyVisible(n)&&this.isElementValueDefined(n),this.invalidate(t),!s.enabled}cascade(e){const t=this.find(e);if(null==t||!1===t.dependsOn)return!1;const s={[e]:!0},i=sortAndFilter(this.form.elements);for(const t in i){const n=i[t],r=n.dependsOn;if("string"==typeof r){const i=this.find(r);void 0!==i&&"string"!=typeof i.dependsOn&&(i.dependsOn=!0),!0===s[r]&&(s[t]=!0,n.checked=!1,n.current=void 0,n.label=void 0,n.items=void 0,n.value=void 0,this.invalidate(t),n.dependsOn===e&&this.enqueue("populate",{name:t}))}else n.dependsOn=!1}return!0}click(e){const t=this.form.elements[e.name];return null!=t&&t.type==FormElementTypes.BUTTONBAR&&this.validate(e)}hasInitialSelectionToDependOn(e){const t=this.form.elements[e];return t.type===FormElementTypes.DROPDOWNLIST&&(void 0!==t.current&&null!==t.current)}hydrate(e){const t=sortAndFilter(this.form.elements);for(const e in t){const t=this.form.elements[e].dependsOn;("string"!=typeof t||this.hasInitialSelectionToDependOn(t))&&this.enqueue("populate",{name:e}),this.enqueue("load",{name:e})}return!0}shouldTriggerValidation(e){const t=this.find(e.name);if(null!=t&&"string"==typeof e.value){const s=e.item;if("string"==typeof s){const e=t.items;if(null!=e){const t=e[s];if(null!=t)return!0===t.validates}return}return!0===t.validates}}validate(e){const t=this.shouldTriggerValidation(e);if(!0===t){const t=this.errors={},s=sortAndFilter(this.form.elements);for(const e in s){const i=s[e];null!=i&&(t[e]=void 0,this.enqueue("validate",{name:e}))}return this.enqueue("verify",{name:e.name,item:e.item,value:e.value,routingKey:"verify"}),!0}return!1===t&&(this.enqueue("end",{name:e.name,item:e.item,value:e.value,routingKey:"end"}),!0)}verify(e){const t=e.name,s=this.form.elements[t],i={status:void 0},n=this.isElementValid(s,!0,i);return t===this.lastFocus?.name&&(this.lastFocus.isInvalid=!n),!n&&(i.status&&(this.errors[t]={status:i.status}),!1===this.nextFocus&&t!==this.lastFocus?.name&&this.isElementPositionBeforeLastFocused(t,!0)&&this.focus(t),!0)}suggest(e){const t=this.form.elements[e.name];return null!=t&&(t.items={message:{label:{status:"trivial"},enabled:!1}},this.invalidate(e.name),!0)}submit(e){if(!this.hasErrors()){for(const e in this.form.elements)this.form.elements[e].error=void 0;return this.enqueue("submit",{name:e.name,item:e.item,value:e.value}),!0}const t=this.errors;for(const e in t){const s=this.form.elements[e];null!=s&&(s.error=t[e],this.invalidate(e))}const s=this.getInvalidElements(),i=[];let n=!1;for(const e of s){const t=this.getParentSection(e);if(isMutuallyExclusiveSection(t)){const e=this.findName(t),s=this.getMutuallyExclusiveSectionGroup(e);if(s){const e=i.find(e=>e.group===s);e?e.element.rowNumber>t.rowNumber&&(e.element=t):(i.push({group:s,element:t}),n=!0)}}else this.isSectionCollapsed(t)&&(t.collapsed=!1,n=!0)}for(const e of i)e.group.expandedSection=e.element;return n&&this.invalidate(),this.errors={},!1}hasErrors(){const e=this.errors;for(const t in e){const s=e[t];if(null!=s)return!0}return!1}find(e){if(null!=e)return"object"==typeof e&&(e=e.name),"string"==typeof e?this.form.elements[e]:void 0}findName(e){for(const t in this.form.elements)if(this.form.elements[t]===e)return t}coerceNumber(e,t){return t=t||this.deriveLocale(),new NumberParser(t).parse(e)}formatNumber(e,t){return t||(t={locale:this.deriveLocale()}),format(t,e)}renderState(e,t,s){return!1}getParentSection(e){const t=e.section;if(!t)return;const s="string"==typeof t?t:t.name;return this.form.elements[s]}isSectionCollapsed(e){return!(!e||e.type!==FormElementTypes.SECTION||!isCollapsibleSection(e)&&!isMutuallyExclusiveSection(e))&&!0===e.collapsed}isElementPositionBeforeLastFocused(e,t=!1){const s=this.lastFocus;if(!s)return!0;if(t&&!s.isInvalid)return!0;if("footer"===e)return!1;if("footer"===s.name)return!0;if(e&&void 0!==s.rowNumber&&void 0!==s.rowIndex){const t=this.form.elements?.[e];if(t)return void 0!==t.rowNumber&&void 0!==t.rowIndex?t.rowNumber<s.rowNumber||t.rowNumber===s.rowNumber&&t.rowIndex<s.rowIndex:t.index<s.rowNumber||t.index===s.rowNumber&&s.rowIndex>0}return!1}setLastFocus(e,t,s){if(this.lastFocus={target:e},!t)return;this.lastFocus.name=t;const i=this.form.elements?.[t];i&&(void 0!==i.rowNumber&&void 0!==i.rowIndex?(this.lastFocus.rowNumber=i.rowNumber,this.lastFocus.rowIndex=i.rowIndex):(this.lastFocus.rowNumber=i.index,this.lastFocus.rowIndex=0),this.lastFocus.isInvalid=s??!!i.error)}getAllSectionElements(){const e={};for(const t in this.form.elements){const s=this.form.elements[t];isSection(s)&&(e[t]=s)}return e}getMutuallyExclusiveSectionGroup(e){let t=this.mutuallyExclusiveSections[e];if(!t){const s=this.find(e);if(!s||!isMutuallyExclusiveSection(s))return;t=new MutuallyExclusiveSectionGroup({elementName:e,element:s});const i=s.format,n=this.getAllSectionElements(),r=Object.keys(sortAndFilter(n,e=>e.rowNumber)),o=r.indexOf(e);for(let e=o-1;e>=0;e--){const s=r[e],n=this.find(s);if(n.format!==i)break;t.unshift({elementName:s,element:n})}for(let e=o+1;e<r.length;e++){const s=r[e],n=this.find(s);if(n.format!==i)break;t.push({elementName:s,element:n})}t.forEach(e=>{this.mutuallyExclusiveSections[e.elementName]=t})}return t}updateMutuallyExclusiveSections(e){this.getMutuallyExclusiveSectionGroup(e).forEach(t=>{t.element.collapsed=t.elementName!==e}),this.refresh()}enforceMutuallyExclusiveConstraints(){const e=Object.keys(this.form.elements).map(e=>({elementName:e,element:this.form.elements[e]})).filter(e=>isMutuallyExclusiveSection(e.element)&&!1!==e.element.visible&&!0!==e.element.collapsed).sort((e,t)=>e.element.rowNumber-t.element.rowNumber),t=[];for(const s of e){const e=this.getMutuallyExclusiveSectionGroup(s.elementName);-1===t.indexOf(e)?t.push(e):s.element.collapsed=!0}}async displayDialog(e,t){await Promise.resolve()}}
1
+ import Bluebird from"bluebird";import{Task}from"../Task.js";import{DEFAULT_LOCALE}from"../constants.js";import*as defs from"./FormDefinition.js";import MutuallyExclusiveSectionGroup from"./MutuallyExclusiveSectionGroup.js";import NumberParser from"./NumberParser.js";import{FormElementTypes}from"./constants.js";import{format}from"./numberFormatter.js";import*as presenter from"./presenter.js";import{isCollapsibleSection,isItemsRef,isMutuallyExclusiveSection,isSection,sortAndFilter,text}from"./utils.js";export{defs};const guid="C0166F74-982A-464E-9FB6-9605CB7649C1:",eventName=guid+"FormEvent";function createEvent(e,t){return new CustomEvent(e,{bubbles:!1,cancelable:!1,detail:t})}function overlay(e,t){switch(typeof e){case"boolean":case"number":case"string":return e;case"object":break;default:return t}if(null===e)return t;if(e instanceof Array){let s=t;null==s&&(s=[]);let i=0;for(const t of e){const n=overlay(t,s[i]);void 0!==n&&(i<e.length?s[i]=n:s.push(n),++i)}return s}let s=t;void 0===s&&(s={});for(const t in e)s[t]=overlay(e[t],s[t]);return s}function createSubscription(e){const t=function(){return void 0!==e&&(t.active=!1,e(),!0)};return t.active=!0,t}export class FormHost{constructor(){this.container=document.createElement("div"),this.custom=!1,this.dismiss=!1,this.enabled=!1,this.errors={},this.form={defaults:{},elements:{}},this.refs={},this.visible=!1,this.domContainers={},this.eventIndex=0,this.eventQueue=[],this.nextFocus=!1,this.nextRefresh=!1,this.pendingValues={},this.mutuallyExclusiveSections={},this.enqueueExternalEvent=e=>{const t={type:`external$${e.name}`,name:"header",argument:e};this.enqueue(t.type,t)}}applyPendingValues(){if(!(this.eventQueue.length>0))for(const[e,t]of Object.entries(this.pendingValues)){const s=this.form.elements[e];if(s){switch(s.type){case"AutoComplete":{const e=Object.entries(s.items??{}).find(([,e])=>e.value===t.value);if(e){const[t,i]=e;s.current=t,s.label=i.label,s.value=i.value}break}case"CheckGroup":case"ItemPicker":case"ListBox":{const e=Object.values(s.items??{}),{value:i}=t;if(e.length>0&&isItemsRef(i)){const t=[];for(const s of i.items){const i=e.find(e=>e.value===s.value);i&&t.push(i)}if(t.length>0){for(const s of e)s.checked=t.includes(s);s.value={refValueType:"items",items:t}}}break}case"DropDownList":case"RadioGroup":{const e=Object.values(s.items??{}).find(e=>e.value===t.value);e&&(s.value=e.value);break}default:throw new Error(`Element type does not support pending values: ${s.type}`)}delete this.pendingValues[e]}else console.warn(`Failed to find element to apply pending values to: ${e}`),delete this.pendingValues[e]}}busy(){if(void 0===this.timerHandle&&void 0!==this.container){let e=setTimeout(()=>this.spin());this.timerHandle=function(){void 0!==e&&(clearTimeout(e),e=void 0)}}}coerceNumber(e,t){return t=t||this.deriveLocale(),new NumberParser(t).parse(e)}dequeue(){const e=this.eventQueue;if(e.length>0){let t=this.eventIndex;const s=e[t++];return t>=e.length?e.length=this.eventIndex=0:this.eventIndex=t,s}}deriveLocale(){return DEFAULT_LOCALE}async displayDialog(e,t){await Promise.resolve()}dispose(){if(!this.dismiss){this.dismiss=!0;const e=this.container;e.dispatchEvent(createEvent(eventName));let t=this.focusObserver;return void 0!==t&&(e.removeEventListener("focus",t,!0),t=void 0),this.idle(),this.unmount(),this.refs={},presenter.releaseForm(this.container),this.container=void 0,this.lastFocus=void 0,this.eventTask=void 0,!0}return!1}enqueue(e,t){return t=this.qualify(e,t),void 0!==this.eventTask?(this.resolveEvent(t),this.eventTask=void 0,t):(this.eventQueue.push(t),t)}find(e){if(null!=e)return"object"==typeof e&&(e=e.name),"string"==typeof e?this.form.elements[e]:void 0}findName(e){for(const t in this.form.elements)if(this.form.elements[t]===e)return t}focus(e){null==e&&(e=!1),!0===e&&(this.lastFocus=void 0),!1===e&&!1===(e=this.nextFocus)&&(e=!0),this.nextFocus=e,this.invalidate(!0!==e?e:void 0)}formatNumber(e,t){return t||(t={locale:this.deriveLocale()}),format(t,e)}hasErrors(){const e=this.errors;for(const t in e){const s=e[t];if(null!=s)return!0}return!1}hasInitialSelectionToDependOn(e){const t=this.form.elements[e];return t.type===FormElementTypes.DROPDOWNLIST&&(void 0!==t.current&&null!==t.current)}hasInvalidChild(e){for(const t in this.form.elements){const s=this.form.elements[t];if(this.isInvalid(s)&&this.getParentSection(s)===e)return!0}return!1}hide(){return void 0!==this.container&&(this.idle(),this.visible&&(this.enabled=!1,this.visible=!1,this.unmount()),!0)}idle(){const e=this.timerHandle;void 0!==e&&(this.timerHandle=void 0,e())}invalidate(e){const t=this.nextRefresh;"string"==typeof e&&!0!==t&&(!1===t?this.nextRefresh={[e]:!0}:t[e]=!0),void 0!==e&&!0!==e||(this.nextRefresh=!0),!1===e&&!1===t&&(this.nextRefresh={})}load(e,t){if(void 0===this.container)return!1;if(this.eventQueue.length=this.eventIndex=0,this.eventTask=void 0,this.errors={},this.lastFocus=void 0,this.nextFocus=!0,this.nextRefresh=!0,this.enqueue("load"),this.enqueue("prepare"),null!=e){let s={defaults:{},elements:{}};s=overlay(e,s),this.form=overlay(t,s);for(const e in this.form.elements){const t={showFilter:!1,checked:!1,enabled:!0,hoisted:!1,visible:!0,overlay:!1,default:!1,validates:!1,readOnly:!1,require:!1,autoActivate:!1};let s=this.form.elements[e];if(s=overlay(s,t),s.items)for(const e in s.items){const t={enabled:!0,checked:!1,visible:!0,default:!1,validates:!1};s.items[e]=overlay(s.items[e],t)}this.form.elements[e]=s}}return!0}observe(){return Bluebird.attempt(()=>{if(void 0!==this.eventTask)return this.eventTask;const e=this.dequeue();return void 0!==e?e:this.show()?(this.eventTask=new Task(e=>{this.resolveEvent=e}),this.eventTask):void 0})}post(e,t){t=this.publish(e,t);const s=this.container;void 0!==s&&s.dispatchEvent(createEvent(eventName,t))}publish(e,t){return this.enabled?(t=this.enqueue(e,t),this.eventQueue.length>0&&this.spin(),t):this.qualify(e,t)}refresh(e){if(!this.custom)if("string"==typeof e){const t=this.refs[e];presenter.refresh(t)}else this.refs={},presenter.refreshForm(this,this.container)}renderFocus(e,t){if(!(this.enabled&&e instanceof HTMLElement&&!1!==this.nextFocus))return!1;const s=this.nextFocus;if(void 0!==t){if(t===s||!0===s&&void 0===this.lastFocus)return this.nextFocus=!1,this.setLastFocus(e,t),e.focus(),!0}else{const t=this.lastFocus?.target;if(!0===s&&t instanceof HTMLElement&&e.contains(t))return this.nextFocus=!1,t.focus(),!0}return!1}renderState(e,t,s){return!1}renderText(e){return"string"==typeof e?e:text.isMarkdown(e)?text.markdownToText(e.markdown):""}renderVisual(e){return presenter.render(e,t=>{t&&e.props.name&&(this.domContainers[e.props.name]=t)})||presenter.renderNone(e)}route(e){switch(e.type){case"changed":return this.cascade(e.name);case"checked":return this.changed(e);case"clicked":return this.click(e);case"prepare":return this.hydrate(e);case"suggest":return this.suggest(e);case"validate":return this.verify(e);case"verify":return this.submit(e)}return!1}show(){const e=this.container;if(void 0===e)return!1;this.custom||void 0!==this.focusObserver||e.addEventListener("focus",this.focusObserver=e=>this.observeFocus(e.target),!0),this.enabled||(this.nextRefresh=!0,this.focus()),this.enforceMutuallyExclusiveConstraints();const t=this.errors;for(const e in t){const s=this.form.elements[e];null!=s&&(s.error=t[e],this.invalidate(e))}return this.idle(),!1!==this.nextRefresh&&(this.enabled=!0,this.visible=!0,this.mount()),this.enabled}spin(){return void 0!==this.container&&(this.idle(),this.visible&&!this.enabled||(this.nextRefresh=!0,this.enabled=!1,this.visible=!0,this.mount()),this.visible)}subscribe(e){let t=e;const s=this.container;if(void 0===s)return createSubscription();const i=function(){t=void 0,s.removeEventListener(eventName,n)},n=function(e){const s=e.detail;void 0!==s?Bluebird.resolve().then(function(){"function"==typeof t&&t(s)}):i()};return s.addEventListener(eventName,n),createSubscription(i)}translateText(e){return"string"==typeof e||text.isMarkdown(e)?e:text.isStatus(e)?e.status:void 0}trap(e){switch(e.type){case"populate":case"load":case"suggest":break;default:return!1}const t=e.name,s=this.find(t);if(null==s)return!1;const i=s.dependsOn;if("string"!=typeof i)return!1;const n=this.find(i);return s.enabled=this.isElementEffectivelyVisible(n)&&this.isElementValueDefined(n),this.invalidate(t),!s.enabled}update(){const e=this.nextRefresh;if(!0===e&&(this.nextRefresh=!1,this.refresh()),"object"==typeof e){this.nextRefresh=!1;for(const t in e)!0===e[t]&&this.refresh(t)}}updateMutuallyExclusiveSections(e){this.getMutuallyExclusiveSectionGroup(e).forEach(t=>{t.element.collapsed=t.elementName!==e}),this.refresh()}cascade(e){const t=this.find(e);if(null==t||!1===t.dependsOn)return!1;const s={[e]:!0},i=sortAndFilter(this.form.elements);for(const t in i){const n=i[t],r=n.dependsOn;if("string"==typeof r){const i=this.find(r);if(void 0!==i&&"string"!=typeof i.dependsOn&&(i.dependsOn=!0),!0===s[r]&&(s[t]=!0,void 0!==n.value&&n.dependsOn===e&&n.persistValueOnRefresh&&(this.pendingValues[t]={label:n.label,value:n.value}),n.checked=!1,n.current=void 0,n.label=void 0,n.items=void 0,n.value=void 0,this.invalidate(t),n.dependsOn===e)){const e=this.pendingValues[t];"AutoComplete"===n.type&&e?this.enqueue("suggest",{name:t,argument:e.label?.toString()}):this.enqueue("populate",{name:t})}}else n.dependsOn=!1}return!0}changed(e){return this.enqueue("changed",{name:e.name,item:e.item,value:e.value}),!0}click(e){const t=this.form.elements[e.name];return null!=t&&t.type==FormElementTypes.BUTTONBAR&&this.validate(e)}hydrate(e){const t=sortAndFilter(this.form.elements);for(const e in t){const t=this.form.elements[e].dependsOn;("string"!=typeof t||this.hasInitialSelectionToDependOn(t))&&this.enqueue("populate",{name:e}),this.enqueue("load",{name:e})}return!0}isElementEffectivelyVisible(e){if(null==e)return!1;const t=this.getParentSection(e);return!1!==t?.visible&&!1!==e.visible}isElementValid(e,t=!0,s={status:void 0}){return null!=e&&(s.status=void 0,text.isInvalidError(e.error)?(s.status="invalid",!1):!0!==e.require||(this.isElementEffectivelyVisible(e)?!!this.isElementValueDefined(e)||(s.status="missing",!1):t))}isElementValueDefined(e){if(null==e)return!1;if(e.type===FormElementTypes.CHECKBOX)return!0;const t=e.current;if(null!=t)return!0;const s=e.value;if(null!=s&&""!==s)return!0;const i=e.items;if(null!=i)for(const e in i){const t=i[e];if(null!=t&&!0===t.checked)return!0}return!1}mount(){const e=this.container,t=e.parentNode;null==t&&document.body.appendChild(e),this.update()}observeFocus(e){if(this.enabled&&e instanceof HTMLElement&&(!this.lastFocus||this.lastFocus.target!==e)){let t=Object.entries(this.domContainers).filter(t=>t[1].contains(e));t.length>1&&(t=t.filter(e=>this.form.elements[e[0]].type!==FormElementTypes.SECTION));const s=t.length>0?t[0][0]:void 0;this.setLastFocus(e,s)}}qualify(e,t){if(null==t&&(t={}),"clicked"===e&&void 0===t.name&&(t.name=this.qualifyDefault(t)),t.type=e,void 0===t.routingKey){const s=t.name;t.routingKey=void 0!==s?e+"$"+s:e}return t}qualifyDefault(e){const t=sortAndFilter(this.form.elements);for(const s in t){const i=t[s];if(null!=i&&!1!==i.visible&&i.enabled){if(i.default)return e.value=i.value,s;const t=sortAndFilter(i.items);if(null!=t)for(const i in t){const n=t[i];if(null!=n&&n.visible&&n.enabled&&n.default)return e.item=i,e.value=n.value,s}}}}shouldTriggerValidation(e){const t=this.find(e.name);if(null!=t&&"string"==typeof e.value){const s=e.item;if("string"==typeof s){const e=t.items;if(null!=e){const t=e[s];if(null!=t)return!0===t.validates}return}return!0===t.validates}}submit(e){if(!this.hasErrors()){for(const e in this.form.elements)this.form.elements[e].error=void 0;return this.enqueue("submit",{name:e.name,item:e.item,value:e.value}),!0}const t=this.errors;for(const e in t){const s=this.form.elements[e];null!=s&&(s.error=t[e],this.invalidate(e))}const s=this.getInvalidElements(),i=[];let n=!1;for(const e of s){const t=this.getParentSection(e);if(isMutuallyExclusiveSection(t)){const e=this.findName(t),s=this.getMutuallyExclusiveSectionGroup(e);if(s){const e=i.find(e=>e.group===s);e?e.element.rowNumber>t.rowNumber&&(e.element=t):(i.push({group:s,element:t}),n=!0)}}else this.isSectionCollapsed(t)&&(t.collapsed=!1,n=!0)}for(const e of i)e.group.expandedSection=e.element;return n&&this.invalidate(),this.errors={},!1}suggest(e){const t=this.form.elements[e.name];return null!=t&&(t.items={message:{label:{status:"trivial"},enabled:!1}},this.invalidate(e.name),!0)}unmount(){const e=this.container,t=e.parentNode;null!=t&&t.removeChild(e)}validate(e){const t=this.shouldTriggerValidation(e);if(!0===t){const t=this.errors={},s=sortAndFilter(this.form.elements);for(const e in s){const i=s[e];null!=i&&(t[e]=void 0,this.enqueue("validate",{name:e}))}return this.enqueue("verify",{name:e.name,item:e.item,value:e.value,routingKey:"verify"}),!0}return!1===t&&(this.enqueue("end",{name:e.name,item:e.item,value:e.value,routingKey:"end"}),!0)}verify(e){const t=e.name,s=this.form.elements[t],i={status:void 0},n=this.isElementValid(s,!0,i);return t===this.lastFocus?.name&&(this.lastFocus.isInvalid=!n),!n&&(i.status&&(this.errors[t]={status:i.status}),!1===this.nextFocus&&t!==this.lastFocus?.name&&this.isElementPositionBeforeLastFocused(t,!0)&&this.focus(t),!0)}enforceMutuallyExclusiveConstraints(){const e=Object.keys(this.form.elements).map(e=>({elementName:e,element:this.form.elements[e]})).filter(e=>isMutuallyExclusiveSection(e.element)&&!1!==e.element.visible&&!0!==e.element.collapsed).sort((e,t)=>e.element.rowNumber-t.element.rowNumber),t=[];for(const s of e){const e=this.getMutuallyExclusiveSectionGroup(s.elementName);-1===t.indexOf(e)?t.push(e):s.element.collapsed=!0}}getAllSectionElements(){const e={};for(const t in this.form.elements){const s=this.form.elements[t];isSection(s)&&(e[t]=s)}return e}getInvalidElements(){return Object.keys(this.form.elements).map(e=>this.form.elements[e]).filter(this.isInvalid)}getMutuallyExclusiveSectionGroup(e){let t=this.mutuallyExclusiveSections[e];if(!t){const s=this.find(e);if(!s||!isMutuallyExclusiveSection(s))return;t=new MutuallyExclusiveSectionGroup({elementName:e,element:s});const i=s.format,n=this.getAllSectionElements(),r=Object.keys(sortAndFilter(n,e=>e.rowNumber)),o=r.indexOf(e);for(let e=o-1;e>=0;e--){const s=r[e],n=this.find(s);if(n.format!==i)break;t.unshift({elementName:s,element:n})}for(let e=o+1;e<r.length;e++){const s=r[e],n=this.find(s);if(n.format!==i)break;t.push({elementName:s,element:n})}t.forEach(e=>{this.mutuallyExclusiveSections[e.elementName]=t})}return t}getParentSection(e){const t=e.section;if(!t)return;const s="string"==typeof t?t:t.name;return this.form.elements[s]}isElementPositionBeforeLastFocused(e,t=!1){const s=this.lastFocus;if(!s)return!0;if(t&&!s.isInvalid)return!0;if("footer"===e)return!1;if("footer"===s.name)return!0;if(e&&void 0!==s.rowNumber&&void 0!==s.rowIndex){const t=this.form.elements?.[e];if(t)return void 0!==t.rowNumber&&void 0!==t.rowIndex?t.rowNumber<s.rowNumber||t.rowNumber===s.rowNumber&&t.rowIndex<s.rowIndex:t.index<s.rowNumber||t.index===s.rowNumber&&s.rowIndex>0}return!1}isInvalid(e){return!!e.error&&!1!==e.visible}isSectionCollapsed(e){return!(!e||e.type!==FormElementTypes.SECTION||!isCollapsibleSection(e)&&!isMutuallyExclusiveSection(e))&&!0===e.collapsed}setLastFocus(e,t,s){if(this.lastFocus={target:e},!t)return;this.lastFocus.name=t;const i=this.form.elements?.[t];i&&(void 0!==i.rowNumber&&void 0!==i.rowIndex?(this.lastFocus.rowNumber=i.rowNumber,this.lastFocus.rowIndex=i.rowIndex):(this.lastFocus.rowNumber=i.index,this.lastFocus.rowIndex=0),this.lastFocus.isInvalid=s??!!i.error)}}
@@ -12,10 +12,50 @@ export interface FormPresenterHost {
12
12
  enabled: boolean;
13
13
  /** The form to render. */
14
14
  form: defs.Form;
15
- /** Posts an event. */
16
- post(type: "changed" | "cancel" | "clicked" | "custom" | "dragged" | "suggest", event?: defs.Event): void;
15
+ /** References all elements. */
16
+ refs: Record<string, FormComponent | undefined>;
17
+ /** Coerces a number from a value. */
18
+ coerceNumber(value: string, locale?: string): number;
19
+ /**
20
+ * Derives the current locale set by the host application (or default if undefined) will be returned.
21
+ */
22
+ deriveLocale(): string;
23
+ /**
24
+ * Shows a dialog in the context of the running application.
25
+ * @param children A function that produces the children for the dialog.
26
+ * @param DialogComponent The type of component to use as the dialog.
27
+ */
28
+ displayDialog(children: (closeDialog: () => void) => ReactNode, DialogComponent: ComponentType<any>): Promise<void>;
17
29
  /** Disposes the form. */
18
30
  dispose(): void;
31
+ /**
32
+ * Passes on an external event (from the host application) to the form's event queue.
33
+ * @param event An event received from the host application.
34
+ */
35
+ enqueueExternalEvent(event: ExternalEvent): void;
36
+ /** Find the element. */
37
+ find(name: string | {
38
+ name: string;
39
+ } | undefined): defs.Element | undefined;
40
+ /** Formats a value into a string. */
41
+ formatNumber(value: number, options?: FormatOptions): string;
42
+ /**
43
+ * Returns `true` if the element has a `type` of `"Section"` and at least one visible child with `error` equal to `true`.
44
+ * @param element
45
+ */
46
+ hasInvalidChild(element: defs.Element): boolean;
47
+ /** Posts an event. */
48
+ post(type: "changed" | "cancel" | "clicked" | "custom" | "dragged" | "suggest", event?: defs.Event): void;
49
+ /** Renders the focus. */
50
+ renderFocus(target: Node, name?: string): boolean;
51
+ /** Renders a component's state. */
52
+ renderState(name: string, type: "geometry", state?: defs.GeometryState[]): boolean;
53
+ /** Renders a component's state. */
54
+ renderState(name: string, type: string, state?: object): boolean;
55
+ /** Renders form text to display text. */
56
+ renderText(text: defs.Text | undefined): string;
57
+ /** Renders a component's visual. */
58
+ renderVisual(component: object): any;
19
59
  /**
20
60
  * Translates the supplied value.
21
61
  * @param content The string or {@link defs.StatusRef} to be translated.
@@ -32,49 +72,9 @@ export interface FormPresenterHost {
32
72
  * @param content The {@link defs.Text} to be translated.
33
73
  */
34
74
  translateText(content: defs.Text | undefined): string | defs.MarkdownRef | undefined;
35
- /** References all elements. */
36
- refs: Record<string, FormComponent | undefined>;
37
- /** Renders the focus. */
38
- renderFocus(target: Node, name?: string): boolean;
39
- /** Renders form text to display text. */
40
- renderText(text: defs.Text | undefined): string;
41
- /** Renders a component's visual. */
42
- renderVisual(component: object): any;
43
- /** Renders a component's state. */
44
- renderState(name: string, type: "geometry", state?: defs.GeometryState[]): boolean;
45
- /** Renders a component's state. */
46
- renderState(name: string, type: string, state?: object): boolean;
47
- /** Find the element. */
48
- find(name: string | {
49
- name: string;
50
- } | undefined): defs.Element | undefined;
51
- /** Coerces a number from a value. */
52
- coerceNumber(value: string, locale?: string): number;
53
- /** Formats a value into a string. */
54
- formatNumber(value: number, options?: FormatOptions): string;
55
- /**
56
- * Derives the current locale set by the host application (or default if undefined) will be returned.
57
- */
58
- deriveLocale(): string;
59
- /**
60
- * Passes on an external event (from the host application) to the form's event queue.
61
- * @param event An event received from the host application.
62
- */
63
- enqueueExternalEvent(event: ExternalEvent): void;
64
75
  /**
65
76
  * Collapses all neighbouring mutually exclusive sections except the one specified.
66
77
  * @param expandedSection The name of the section to be expanded. All others in the group will be collapsed.
67
78
  */
68
79
  updateMutuallyExclusiveSections(expandedSection: string): void;
69
- /**
70
- * Shows a dialog in the context of the running application.
71
- * @param children A function that produces the children for the dialog.
72
- * @param DialogComponent The type of component to use as the dialog.
73
- */
74
- displayDialog(children: (closeDialog: () => void) => ReactNode, DialogComponent: ComponentType<any>): Promise<void>;
75
- /**
76
- * Returns `true` if the element has a `type` of `"Section"` and at least one visible child with `error` equal to `true`.
77
- * @param element
78
- */
79
- hasInvalidChild(element: defs.Element): boolean;
80
80
  }
@@ -3,10 +3,10 @@ import type * as defs from "./FormDefinition";
3
3
  * The definition of a Form Element along with its name.
4
4
  */
5
5
  export type ElementKeyValuePair = {
6
- /** The name of the form element as defined in the form. */
7
- elementName: string;
8
6
  /** The implementation of the element itself. */
9
7
  element: defs.Element;
8
+ /** The name of the form element as defined in the form. */
9
+ elementName: string;
10
10
  };
11
11
  /**
12
12
  * This facilitates the lookup of related Section form elements, for cases where
@@ -28,14 +28,14 @@ export default class MutuallyExclusiveSectionGroup extends Array<ElementKeyValue
28
28
  * if none are expanded, this returns undefined.
29
29
  */
30
30
  get expandedSection(): defs.Element | undefined;
31
+ /**
32
+ * Gets a value indicating if a section is currently expanded in this group.
33
+ */
34
+ get hasExpandedSection(): boolean;
31
35
  /**
32
36
  * Sets the currently expanded section in this group.
33
37
  * All others are collapsed.
34
38
  */
35
39
  set expandedSection(element: defs.Element | undefined);
36
40
  getElement(elementName: string): defs.Element | undefined;
37
- /**
38
- * Gets a value indicating if a section is currently expanded in this group.
39
- */
40
- get hasExpandedSection(): boolean;
41
41
  }
@@ -1 +1 @@
1
- export default class MutuallyExclusiveSectionGroup extends Array{get expandedSection(){return this.find(e=>!0!==e.element.collapsed)?.element}set expandedSection(e){const t=this.find(t=>t.element===e);if(!t)throw new Error("Element is not present in the group.");this.forEach(e=>e.element.collapsed=e!==t)}getElement(e){return this.find(t=>t.elementName===e)?.element}get hasExpandedSection(){return void 0!==this.expandedSection}}
1
+ export default class MutuallyExclusiveSectionGroup extends Array{get expandedSection(){return this.find(e=>!0!==e.element.collapsed)?.element}get hasExpandedSection(){return void 0!==this.expandedSection}set expandedSection(e){const t=this.find(t=>t.element===e);if(!t)throw new Error("Element is not present in the group.");this.forEach(e=>e.element.collapsed=e!==t)}getElement(e){return this.find(t=>t.elementName===e)?.element}}
@@ -8,11 +8,11 @@
8
8
  */
9
9
  export default class NumberParser {
10
10
  private _biDirectionalChars;
11
- private _group;
12
11
  private _decimal;
12
+ private _group;
13
+ private _index;
13
14
  private _minus;
14
15
  private _numeral;
15
- private _index;
16
16
  /**
17
17
  * Creates a new instance of the {@link NumberParser} class.
18
18
  * @param locale The locale to use for parsing the text.
@@ -3,15 +3,15 @@
3
3
  */
4
4
  export default class WorkflowColor {
5
5
  private values;
6
- get r(): number;
7
- get g(): number;
8
- get b(): number;
9
- get a(): number;
10
6
  constructor(value: number[] | string);
7
+ get a(): number;
8
+ get b(): number;
9
+ get g(): number;
10
+ get r(): number;
11
+ static fromJSON(value: number[]): WorkflowColor;
11
12
  clone(): WorkflowColor;
12
13
  equals(other: WorkflowColor): boolean;
13
14
  toCss(): string;
14
15
  toJSON(): number[];
15
16
  toString(): string;
16
- static fromJSON(value: number[]): WorkflowColor;
17
17
  }