@genesislcap/foundation-forms 14.496.2-alpha-da9ccbd.0 → 14.497.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 (39) hide show
  1. package/dist/custom-elements.json +341 -1
  2. package/dist/dts/filters/filters.d.ts +0 -1
  3. package/dist/dts/filters/filters.d.ts.map +1 -1
  4. package/dist/dts/form.d.ts +94 -1
  5. package/dist/dts/form.d.ts.map +1 -1
  6. package/dist/dts/form.styles.d.ts.map +1 -1
  7. package/dist/dts/form.template.d.ts.map +1 -1
  8. package/dist/dts/index.d.ts +3 -0
  9. package/dist/dts/index.d.ts.map +1 -1
  10. package/dist/dts/jsonforms/renderers/CategorizationWrapperRenderer.d.ts.map +1 -1
  11. package/dist/dts/react.d.ts +10 -0
  12. package/dist/dts/review.d.ts +34 -0
  13. package/dist/dts/review.d.ts.map +1 -0
  14. package/dist/dts/review.styles.d.ts +3 -0
  15. package/dist/dts/review.styles.d.ts.map +1 -0
  16. package/dist/dts/review.template.d.ts +6 -0
  17. package/dist/dts/review.template.d.ts.map +1 -0
  18. package/dist/dts/utils/index.d.ts +1 -0
  19. package/dist/dts/utils/index.d.ts.map +1 -1
  20. package/dist/dts/utils/review-utils.d.ts +82 -0
  21. package/dist/dts/utils/review-utils.d.ts.map +1 -0
  22. package/dist/dts/utils/schema-utils.d.ts +12 -0
  23. package/dist/dts/utils/schema-utils.d.ts.map +1 -1
  24. package/dist/esm/form.js +132 -3
  25. package/dist/esm/form.styles.js +9 -2
  26. package/dist/esm/form.template.js +63 -25
  27. package/dist/esm/index.js +3 -0
  28. package/dist/esm/jsonforms/renderers/CategorizationWrapperRenderer.js +1 -45
  29. package/dist/esm/review.js +63 -0
  30. package/dist/esm/review.styles.js +93 -0
  31. package/dist/esm/review.template.js +39 -0
  32. package/dist/esm/utils/index.js +1 -0
  33. package/dist/esm/utils/review-utils.js +241 -0
  34. package/dist/esm/utils/schema-utils.js +48 -0
  35. package/dist/foundation-forms.api.json +428 -0
  36. package/dist/foundation-forms.d.ts +224 -2
  37. package/dist/react.cjs +7 -0
  38. package/dist/react.mjs +6 -0
  39. package/package.json +15 -15
@@ -9,6 +9,7 @@ import { FASTElement } from '@microsoft/fast-element';
9
9
  import { FilterMode } from '@genesislcap/foundation-ui';
10
10
  import { FoundationElement } from '@microsoft/fast-foundation';
11
11
  import { FoundationLayoutContainer } from '@genesislcap/foundation-utils';
12
+ import { JsonFormsCore } from '@jsonforms/core';
12
13
  import { JsonFormsState } from '@jsonforms/core';
13
14
  import type { JsonSchema } from '@jsonforms/core';
14
15
  import { JSONSchema7 } from 'json-schema';
@@ -179,6 +180,32 @@ export declare type ArrayRendererOptions = {
179
180
  showRowStatusIndicator?: boolean;
180
181
  };
181
182
 
183
+ /**
184
+ * Builds the review panel's fields grouped into sections by their nearest `Group` layout.
185
+ * Sections are formed from consecutive runs of the same group title as fields are
186
+ * encountered in the UI schema — not a global title lookup — so two fields that happen to
187
+ * share a title (including `null`, for ungrouped fields) don't get merged into one section
188
+ * unless they're actually adjacent. Otherwise an ungrouped field appearing after a Group
189
+ * would jump back up next to earlier ungrouped fields instead of staying where it sits in
190
+ * the form, and two distinct Groups with the same label would collapse into one. Falls back
191
+ * to a flat, single ungrouped section when no UI schema is available.
192
+ *
193
+ * Async because connected-select fields backed by `options.allOptionsResourceName` (rather
194
+ * than a static `options.data`) resolve their display label with a criteria-filtered fetch
195
+ * — see `resolveResourceOptionLabel`. The UI schema is walked synchronously to collect one
196
+ * value-resolution promise per field (preserving encounter order), then all promises settle
197
+ * in parallel via `Promise.all` before fields are added to their sections — so a slow fetch
198
+ * for one field can't reorder fields that resolved faster.
199
+ *
200
+ * This is the single walker of the UI schema for review purposes — `Form` calls it directly
201
+ * to populate `Review.sections`. Don't reimplement this traversal elsewhere; the two
202
+ * previously did drift (a since-removed `collectReviewFields` resolved labels via
203
+ * `resolveOptionLabel` / `resolveEnumLabel` only, silently skipping `resolveResourceOptionLabel`
204
+ * and showing raw ids for connected-select fields).
205
+ * @internal
206
+ */
207
+ export declare function buildReviewSections(data: Record<string, any>, uiSchema: any, schema: any): Promise<ReviewSection[]>;
208
+
182
209
  /**
183
210
  * Tracks the submission status and result for a single row in bulk insert mode.
184
211
  * @public
@@ -596,6 +623,14 @@ export declare function extractFieldsFromUiSchema(uiSchema: UiSchema): Array<{
596
623
  isHidden: boolean;
597
624
  }>;
598
625
 
626
+ /**
627
+ * Filters review sections down to fields whose label or value contains `query`
628
+ * (case-insensitive). Sections left with no matching fields are dropped entirely.
629
+ * Returns `sections` unchanged when `query` is blank.
630
+ * @internal
631
+ */
632
+ export declare function filterReviewSections(sections: ReviewSection[], query: string): ReviewSection[];
633
+
599
634
  /**
600
635
  * Foundation filters component for automatically generated filters based on json schema
601
636
  * obtained from the api, supplied initial data or supplied JSON schema.
@@ -738,7 +773,6 @@ declare const Filters_base: (new (...args: any[]) => {
738
773
  #_hasFirstLoaded: boolean;
739
774
  #_cleanupTimeout: NodeJS.Timeout;
740
775
  #_shouldForceLifecycle: boolean;
741
- #_blockedDisconnectSurvivedGracePeriod: boolean;
742
776
  cloneNode(deep?: boolean): Node;
743
777
  deepClone(): Node;
744
778
  get shouldRunDisconnect(): boolean;
@@ -1197,6 +1231,16 @@ export declare class Form extends Form_base {
1197
1231
  * @internal
1198
1232
  */
1199
1233
  serverFieldErrors: ErrorObject[];
1234
+ /**
1235
+ * Reference to the json-forms child element — used to read live validation
1236
+ * errors at submit time so review mode never activates when the form is invalid.
1237
+ * @internal
1238
+ */
1239
+ jsonFormsEl: {
1240
+ jsonforms?: {
1241
+ core?: JsonFormsCore;
1242
+ };
1243
+ };
1200
1244
  /**
1201
1245
  * Stores the approval message entered by the user.
1202
1246
  * @internal
@@ -1320,6 +1364,24 @@ export declare class Form extends Form_base {
1320
1364
  * @public
1321
1365
  */
1322
1366
  bulkInsert: boolean;
1367
+ /**
1368
+ * Text to appear on submit button
1369
+ * @default Submit
1370
+ * @public
1371
+ */
1372
+ submitButtonText: string;
1373
+ /**
1374
+ * Text to appear on submit button in bulk insert mode
1375
+ * @default Submit AllS
1376
+ * @public
1377
+ */
1378
+ bulkSubmitButtonText: string;
1379
+ /**
1380
+ * Text to appear on reset button
1381
+ * @default Submit
1382
+ * @public
1383
+ */
1384
+ resetButtonText: string;
1323
1385
  /**
1324
1386
  * Minimum number of items required in bulk insert mode.
1325
1387
  * @public
@@ -1340,16 +1402,80 @@ export declare class Form extends Form_base {
1340
1402
  * @internal
1341
1403
  */
1342
1404
  private userProvidedUiSchema;
1405
+ /**
1406
+ * When enabled, clicking submit with no validation errors shows a read-only preview
1407
+ * of the form data before the final submission.
1408
+ * @public
1409
+ */
1410
+ showSubmitReview: boolean;
1411
+ /**
1412
+ * Text to appear on reset button
1413
+ * @public
1414
+ */
1415
+ reviewButtonText: string;
1416
+ /**
1417
+ * Heading shown at the top of the review panel.
1418
+ * @public
1419
+ */
1420
+ reviewHeading: string;
1421
+ /**
1422
+ * Name of a top-level data field whose value is shown as an identifier next to the
1423
+ * review heading (e.g. a record's primary key). No identifier is shown when unset.
1424
+ * @public
1425
+ */
1426
+ reviewIdField: string;
1343
1427
  /**
1344
1428
  * Tracks the submission status for each row in bulk insert mode.
1345
1429
  * Key is the row index, value is the status object.
1346
1430
  * @public
1347
1431
  */
1348
1432
  rowSubmitStatuses: Map<number, BulkRowStatus>;
1433
+ /**
1434
+ * Whether the form is currently showing the submit-review preview panel.
1435
+ * @internal
1436
+ */
1437
+ reviewMode: boolean;
1438
+ /**
1439
+ * Field label/value pairs rendered in the review panel, grouped into sections.
1440
+ * @internal
1441
+ */
1442
+ reviewSections: ReviewSection[];
1443
+ /**
1444
+ * Value of `reviewIdField` resolved from the current form data, if set.
1445
+ * @internal
1446
+ */
1447
+ get reviewRecordId(): string | undefined;
1349
1448
  /**
1350
1449
  * @internal
1351
1450
  */
1352
1451
  _submit(): Promise<void>;
1452
+ /**
1453
+ * Called from the review panel to go back to the form.
1454
+ * @internal
1455
+ */
1456
+ backFromReview(): void;
1457
+ /**
1458
+ * Called from the review panel submit button to perform the actual submission.
1459
+ * Intentionally skips `confirmationMessage` — that gate already ran once in `_submit()`
1460
+ * before review mode was entered, and re-confirming here would ask the user twice.
1461
+ * @internal
1462
+ */
1463
+ _submitFromReview(): Promise<void>;
1464
+ /**
1465
+ * Whether the form currently has validation errors. Reads live errors directly from the
1466
+ * json-forms element when it's mounted, so we always use the current validation state
1467
+ * (this.errors can lag in edge cases such as required fields with empty-string values not
1468
+ * yet reported via data-change). Falls back to this.errors when json-forms isn't mounted
1469
+ * (e.g. while the read-only review panel is showing), which is safe since no interactive
1470
+ * editing happens during review.
1471
+ * @internal
1472
+ */
1473
+ private hasValidationErrors;
1474
+ /**
1475
+ * Performs the actual API submission after review (or directly when review is disabled).
1476
+ * @internal
1477
+ */
1478
+ private _performSubmit;
1353
1479
  /**
1354
1480
  * Handles bulk insert submission by iterating through items and submitting each separately.
1355
1481
  * Updates rowSubmitStatuses to provide row-level feedback.
@@ -1477,7 +1603,6 @@ declare const Form_base: (new (...args: any[]) => {
1477
1603
  #_hasFirstLoaded: boolean;
1478
1604
  #_cleanupTimeout: NodeJS.Timeout;
1479
1605
  #_shouldForceLifecycle: boolean;
1480
- #_blockedDisconnectSurvivedGracePeriod: boolean;
1481
1606
  cloneNode(deep?: boolean): Node;
1482
1607
  deepClone(): Node;
1483
1608
  get shouldRunDisconnect(): boolean;
@@ -1839,6 +1964,14 @@ declare const Form_base: (new (...args: any[]) => {
1839
1964
  focus(options?: FocusOptions): void;
1840
1965
  }) & typeof FoundationElement;
1841
1966
 
1967
+ /**
1968
+ * Converts a raw field value to a display string for the review panel.
1969
+ * Arrays of primitives are comma-joined; arrays of objects and plain objects
1970
+ * are rendered as readable `key: value` lines.
1971
+ * @internal
1972
+ */
1973
+ export declare function formatValueForReview(value: any): string;
1974
+
1842
1975
  /**
1843
1976
  * Detail payload for the `data-change` event fired by {@link Form} and `JSONForms` whenever
1844
1977
  * the bound form data changes.
@@ -1864,6 +1997,12 @@ export declare type FormDataChangeEventDetail = {
1864
1997
  path?: string;
1865
1998
  };
1866
1999
 
2000
+ /** @internal */
2001
+ export declare const foundationFormReviewStyles: ElementStyles;
2002
+
2003
+ /** @internal */
2004
+ export declare const foundationFormReviewTemplate: ViewTemplate<Review, any>;
2005
+
1867
2006
  /** @internal */
1868
2007
  export declare const foundationFormStyles: ElementStyles;
1869
2008
 
@@ -1941,9 +2080,19 @@ export declare enum GenesisType {
1941
2080
  */
1942
2081
  export declare const getAnyOfErrorMessage: (errors: Array<any> | undefined, schema: any, controlPath: string | undefined, uiCustomMsg?: string) => string;
1943
2082
 
2083
+ /**
2084
+ * Navigates a `/properties/`-separated path in data to support nested object scopes
2085
+ * such as `ADDRESS/properties/STREET` produced by Group layout UI schemas.
2086
+ * @internal
2087
+ */
2088
+ export declare function getDataValueAtPath(data: any, fieldName: string): any;
2089
+
1944
2090
  /** @internal */
1945
2091
  export declare const getPrefixedForm: (prefix: any) => ViewTemplate<Form, any>;
1946
2092
 
2093
+ /** @internal */
2094
+ export declare const getPrefixedReview: (prefix: any) => ViewTemplate<Review, any>;
2095
+
1947
2096
  /**
1948
2097
  * Fixed height (CSS value) for vertical categorization when `layout` is `{ type: 'vertical'; height?: string }`.
1949
2098
  * @public
@@ -2300,6 +2449,79 @@ export declare type RendererEntry = {
2300
2449
  */
2301
2450
  export declare const renderers: any[];
2302
2451
 
2452
+ /**
2453
+ * For plain enum combobox fields (no options.data), applies the same `capitalCase`
2454
+ * transform the renderer uses — e.g. `SEMI_ANNUAL` → `Semi Annual`.
2455
+ * Navigates the JSON schema via the fieldName path to confirm the field is an enum
2456
+ * before transforming. Returns `null` for non-enum fields.
2457
+ * @internal
2458
+ */
2459
+ export declare function resolveEnumLabel(raw: any, fieldName: string, schema: any): string | null;
2460
+
2461
+ /**
2462
+ * Looks up the display label for a raw value from `options.data` (used by segmented,
2463
+ * radio group, connected-select, and enum-with-explicit-data renderers). Honors
2464
+ * `options.valueField`/`options.labelField` when set, defaulting to `value`/`label`.
2465
+ * Returns `null` when no match found.
2466
+ * @internal
2467
+ */
2468
+ export declare function resolveOptionLabel(raw: any, options: any): string | null;
2469
+
2470
+ /**
2471
+ * Resolves the display label for a connected-select field backed by
2472
+ * `options.allOptionsResourceName` (a Data Server/Request Server resource) rather than a
2473
+ * static `options.data` array — e.g. `ConnectedSelectControlRenderer` in async/remote mode.
2474
+ * Fetches a single row via a criteria-filtered snapshot matching `valueField === raw`,
2475
+ * then reads `labelField` off the returned row. Returns `null` when there's no resource
2476
+ * to query, the resource can't be reached, or no row matches.
2477
+ * @internal
2478
+ */
2479
+ export declare function resolveResourceOptionLabel(raw: any, options: any): Promise<string | null>;
2480
+
2481
+ /**
2482
+ * Read-only preview panel shown by `<foundation-form>` when `show-submit-review` is enabled.
2483
+ * Renders the reviewed data grouped into sections with a header and a filter field.
2484
+ * @public
2485
+ */
2486
+ export declare class Review extends FASTElement {
2487
+ prefix: string;
2488
+ /**
2489
+ * Title shown in the review header.
2490
+ * @public
2491
+ */
2492
+ heading: string;
2493
+ /**
2494
+ * Optional identifier shown next to the heading, e.g. a record's primary key.
2495
+ * @public
2496
+ */
2497
+ recordId: string;
2498
+ /**
2499
+ * Sections of label/value pairs to render, grouped by their nearest UI schema `Group`.
2500
+ * @public
2501
+ */
2502
+ sections: ReviewSection[];
2503
+ /**
2504
+ * Free-text query filtering fields by label or value. Sections with no matching
2505
+ * fields are hidden.
2506
+ * @internal
2507
+ */
2508
+ filterText: string;
2509
+ /** @internal */
2510
+ get filteredSections(): ReviewSection[];
2511
+ }
2512
+
2513
+ /** @public */
2514
+ export declare type ReviewField = {
2515
+ label: string;
2516
+ value: string;
2517
+ };
2518
+
2519
+ /** @public */
2520
+ export declare type ReviewSection = {
2521
+ title: string | null;
2522
+ fields: ReviewField[];
2523
+ };
2524
+
2303
2525
  /**
2304
2526
  * Detail payload for the `row-status-changed` event fired by {@link Form} whenever the
2305
2527
  * submission status of one or all bulk insert rows changes.
package/dist/react.cjs CHANGED
@@ -17,6 +17,7 @@ const { StepperWrapper: StepperWrapperWC } = require('./esm/jsonforms/renderers/
17
17
  const { VerticalCategorizationWrapper: VerticalCategorizationWrapperWC } = require('./esm/jsonforms/renderers/VerticalCategorizationWrapperRenderer.js');
18
18
  const { DispatchRenderer: DispatchRendererWC } = require('./esm/jsonforms/renderers/dispatch-renderer.js');
19
19
  const { FoundationReactSlot: FoundationReactSlotWC } = require('./esm/jsonforms/renderers/foundation-react-slot.js');
20
+ const { Review: ReviewWC } = require('./esm/review.js');
20
21
 
21
22
  function _mergeRefs(...refs) {
22
23
  return (value) => {
@@ -104,6 +105,11 @@ const Form = React.forwardRef(function Form(props, ref) {
104
105
  return React.createElement(customElements.getName(FormWC) ?? 'foundation-form', { ...rest, ref: _mergeRefs(_innerRef, ref) }, children);
105
106
  });
106
107
 
108
+ const Review = React.forwardRef(function Review(props, ref) {
109
+ const { children, ...rest } = props;
110
+ return React.createElement(customElements.getName(ReviewWC) ?? 'foundation-form-review', { ...rest, ref }, children);
111
+ });
112
+
107
113
  const Filters = React.forwardRef(function Filters(props, ref) {
108
114
  const { children, ...rest } = props;
109
115
  return React.createElement(customElements.getName(FiltersWC) ?? 'foundation-filters', { ...rest, ref }, children);
@@ -168,6 +174,7 @@ const FoundationReactSlot = React.forwardRef(function FoundationReactSlot(props,
168
174
 
169
175
  module.exports = {
170
176
  Form,
177
+ Review,
171
178
  Filters,
172
179
  JSONForms,
173
180
  ArrayListWrapper,
package/dist/react.mjs CHANGED
@@ -15,6 +15,7 @@ import { StepperWrapper as StepperWrapperWC } from './esm/jsonforms/renderers/St
15
15
  import { VerticalCategorizationWrapper as VerticalCategorizationWrapperWC } from './esm/jsonforms/renderers/VerticalCategorizationWrapperRenderer.js';
16
16
  import { DispatchRenderer as DispatchRendererWC } from './esm/jsonforms/renderers/dispatch-renderer.js';
17
17
  import { FoundationReactSlot as FoundationReactSlotWC } from './esm/jsonforms/renderers/foundation-react-slot.js';
18
+ import { Review as ReviewWC } from './esm/review.js';
18
19
 
19
20
  function _mergeRefs(...refs) {
20
21
  return (value) => {
@@ -102,6 +103,11 @@ export const Form = React.forwardRef(function Form(props, ref) {
102
103
  return React.createElement(customElements.getName(FormWC) ?? 'foundation-form', { ...rest, ref: _mergeRefs(_innerRef, ref) }, children);
103
104
  });
104
105
 
106
+ export const Review = React.forwardRef(function Review(props, ref) {
107
+ const { children, ...rest } = props;
108
+ return React.createElement(customElements.getName(ReviewWC) ?? 'foundation-form-review', { ...rest, ref }, children);
109
+ });
110
+
105
111
  export const Filters = React.forwardRef(function Filters(props, ref) {
106
112
  const { children, ...rest } = props;
107
113
  return React.createElement(customElements.getName(FiltersWC) ?? 'foundation-filters', { ...rest, ref }, children);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/foundation-forms",
3
3
  "description": "Genesis Foundation Forms",
4
- "version": "14.496.2-alpha-da9ccbd.0",
4
+ "version": "14.497.0",
5
5
  "sideEffects": false,
6
6
  "license": "SEE LICENSE IN license.txt",
7
7
  "main": "dist/esm/index.js",
@@ -59,13 +59,13 @@
59
59
  }
60
60
  },
61
61
  "devDependencies": {
62
- "@genesislcap/foundation-testing": "14.496.2-alpha-da9ccbd.0",
63
- "@genesislcap/genx": "14.496.2-alpha-da9ccbd.0",
64
- "@genesislcap/rollup-builder": "14.496.2-alpha-da9ccbd.0",
65
- "@genesislcap/ts-builder": "14.496.2-alpha-da9ccbd.0",
66
- "@genesislcap/uvu-playwright-builder": "14.496.2-alpha-da9ccbd.0",
67
- "@genesislcap/vite-builder": "14.496.2-alpha-da9ccbd.0",
68
- "@genesislcap/webpack-builder": "14.496.2-alpha-da9ccbd.0",
62
+ "@genesislcap/foundation-testing": "14.497.0",
63
+ "@genesislcap/genx": "14.497.0",
64
+ "@genesislcap/rollup-builder": "14.497.0",
65
+ "@genesislcap/ts-builder": "14.497.0",
66
+ "@genesislcap/uvu-playwright-builder": "14.497.0",
67
+ "@genesislcap/vite-builder": "14.497.0",
68
+ "@genesislcap/webpack-builder": "14.497.0",
69
69
  "@types/json-schema": "^7.0.11",
70
70
  "@types/papaparse": "^5.3.14"
71
71
  },
@@ -82,12 +82,12 @@
82
82
  }
83
83
  },
84
84
  "dependencies": {
85
- "@genesislcap/foundation-comms": "14.496.2-alpha-da9ccbd.0",
86
- "@genesislcap/foundation-criteria": "14.496.2-alpha-da9ccbd.0",
87
- "@genesislcap/foundation-logger": "14.496.2-alpha-da9ccbd.0",
88
- "@genesislcap/foundation-notifications": "14.496.2-alpha-da9ccbd.0",
89
- "@genesislcap/foundation-ui": "14.496.2-alpha-da9ccbd.0",
90
- "@genesislcap/foundation-utils": "14.496.2-alpha-da9ccbd.0",
85
+ "@genesislcap/foundation-comms": "14.497.0",
86
+ "@genesislcap/foundation-criteria": "14.497.0",
87
+ "@genesislcap/foundation-logger": "14.497.0",
88
+ "@genesislcap/foundation-notifications": "14.497.0",
89
+ "@genesislcap/foundation-ui": "14.497.0",
90
+ "@genesislcap/foundation-utils": "14.497.0",
91
91
  "@json-schema-tools/dereferencer": "^1.6.1",
92
92
  "@jsonforms/core": "^3.2.1",
93
93
  "@microsoft/fast-components": "2.30.6",
@@ -109,5 +109,5 @@
109
109
  "access": "public"
110
110
  },
111
111
  "customElements": "dist/custom-elements.json",
112
- "gitHead": "daac29f621ee844cc6e269c0b8bd52c56bff8cf0"
112
+ "gitHead": "8859a3cd83bd40fc5e5bbff9be5ebe02380fb6ec"
113
113
  }