@genesislcap/foundation-forms 14.488.2-FUI-2571.3 → 14.488.2-GENC-1351.2

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 (37) hide show
  1. package/dist/custom-elements.json +1115 -1775
  2. package/dist/dts/form.d.ts +0 -77
  3. package/dist/dts/form.d.ts.map +1 -1
  4. package/dist/dts/form.styles.d.ts.map +1 -1
  5. package/dist/dts/form.template.d.ts.map +1 -1
  6. package/dist/dts/index.d.ts +0 -3
  7. package/dist/dts/index.d.ts.map +1 -1
  8. package/dist/dts/jsonforms/renderers/CategorizationWrapperRenderer.d.ts.map +1 -1
  9. package/dist/dts/react.d.ts +0 -10
  10. package/dist/dts/utils/index.d.ts +0 -1
  11. package/dist/dts/utils/index.d.ts.map +1 -1
  12. package/dist/dts/utils/schema-utils.d.ts +0 -12
  13. package/dist/dts/utils/schema-utils.d.ts.map +1 -1
  14. package/dist/esm/form.js +1 -120
  15. package/dist/esm/form.styles.js +2 -9
  16. package/dist/esm/form.template.js +24 -58
  17. package/dist/esm/index.js +0 -3
  18. package/dist/esm/jsonforms/renderers/CategorizationWrapperRenderer.js +45 -1
  19. package/dist/esm/utils/index.js +0 -1
  20. package/dist/esm/utils/schema-utils.js +0 -48
  21. package/dist/foundation-forms.api.json +112 -1227
  22. package/dist/foundation-forms.d.ts +0 -200
  23. package/dist/react.cjs +0 -7
  24. package/dist/react.mjs +0 -6
  25. package/package.json +15 -15
  26. package/dist/dts/review.d.ts +0 -34
  27. package/dist/dts/review.d.ts.map +0 -1
  28. package/dist/dts/review.styles.d.ts +0 -3
  29. package/dist/dts/review.styles.d.ts.map +0 -1
  30. package/dist/dts/review.template.d.ts +0 -6
  31. package/dist/dts/review.template.d.ts.map +0 -1
  32. package/dist/dts/utils/review-utils.d.ts +0 -73
  33. package/dist/dts/utils/review-utils.d.ts.map +0 -1
  34. package/dist/esm/review.js +0 -63
  35. package/dist/esm/review.styles.js +0 -93
  36. package/dist/esm/review.template.js +0 -38
  37. package/dist/esm/utils/review-utils.js +0 -269
@@ -1,93 +0,0 @@
1
- import { designUnit, strokeWidth } from '@microsoft/fast-components';
2
- import { css } from '@microsoft/fast-element';
3
- import { forcedColorsStylesheetBehavior } from '@microsoft/fast-foundation';
4
- import { SystemColors } from '@microsoft/fast-web-utilities';
5
- /** @internal */
6
- export const foundationFormReviewStyles = css `
7
- foundation-form-review {
8
- display: flex;
9
- flex-direction: column;
10
- flex: 1;
11
- min-height: 0;
12
- overflow: hidden;
13
- }
14
-
15
- foundation-form-review .review-header {
16
- display: flex;
17
- align-items: baseline;
18
- gap: calc(${designUnit} * 2px);
19
- padding: calc(${designUnit} * 2px) calc(${designUnit} * 2px) calc(${designUnit} * 1px);
20
- border-bottom: calc(${strokeWidth} * 1px) solid var(--neutral-stroke-rest, rgb(0 0 0 / 12%));
21
- }
22
-
23
- foundation-form-review .review-title {
24
- font-size: var(--type-ramp-plus-1-font-size, 1rem);
25
- line-height: var(--type-ramp-plus-1-line-height, 1.5rem);
26
- font-weight: 600;
27
- color: var(--neutral-foreground-rest);
28
- }
29
-
30
- foundation-form-review .review-id {
31
- font-family: var(--mono-font-family, 'Courier New', Courier, monospace);
32
- font-size: var(--type-ramp-base-font-size, 0.875rem);
33
- color: var(--neutral-foreground-hint, rgb(0 0 0 / 60%));
34
- }
35
-
36
- foundation-form-review .review-filter {
37
- padding: calc(${designUnit} * 2px);
38
- }
39
-
40
- foundation-form-review .review-filter-input {
41
- width: 100%;
42
- }
43
-
44
- foundation-form-review .review-body {
45
- flex: 1;
46
- overflow-y: auto;
47
- min-height: 0;
48
- scrollbar-color: var(--neutral-stroke-rest) transparent;
49
- }
50
-
51
- foundation-form-review .review-section-header {
52
- font-size: var(--type-ramp-minus-1-font-size, 0.75rem);
53
- line-height: var(--type-ramp-minus-1-line-height, 1rem);
54
- font-weight: 600;
55
- letter-spacing: 0.04em;
56
- text-transform: uppercase;
57
- color: var(--neutral-foreground-hint, rgb(0 0 0 / 60%));
58
- background-color: var(--neutral-layer-2, rgb(0 0 0 / 4%));
59
- padding: calc(${designUnit} * 1px) calc(${designUnit} * 2px);
60
- margin-top: calc(${designUnit} * 3px);
61
- }
62
-
63
- foundation-form-review .review-field {
64
- display: flex;
65
- align-items: baseline;
66
- justify-content: space-between;
67
- gap: calc(${designUnit} * 2px);
68
- padding: calc(${designUnit} * 1.5px) calc(${designUnit} * 2px);
69
- border-bottom: calc(${strokeWidth} * 1px) solid var(--neutral-stroke-rest, rgb(0 0 0 / 12%));
70
- }
71
-
72
- foundation-form-review .review-field:last-child {
73
- border-bottom: none;
74
- }
75
-
76
- foundation-form-review .review-field-label {
77
- color: var(--neutral-foreground-hint, rgb(0 0 0 / 60%));
78
- font-size: var(--type-ramp-base-font-size, 0.875rem);
79
- flex-shrink: 0;
80
- }
81
-
82
- foundation-form-review .review-field-value {
83
- color: var(--neutral-foreground-rest);
84
- font-size: var(--type-ramp-base-font-size, 0.875rem);
85
- text-align: right;
86
- word-break: break-word;
87
- white-space: pre-wrap;
88
- }
89
- `.withBehaviors(forcedColorsStylesheetBehavior(css `
90
- foundation-form-review {
91
- background: ${SystemColors.Canvas};
92
- }
93
- `));
@@ -1,38 +0,0 @@
1
- import { sync } from '@genesislcap/foundation-utils';
2
- import { html, repeat, when } from '@microsoft/fast-element';
3
- /** @internal */
4
- export const getPrefixedReview = (prefix) => html `
5
- <template>
6
- <div class="review-header">
7
- <span class="review-title">${(x) => x.heading}</span>
8
- ${when((x) => x.recordId, html `
9
- <span class="review-id">${(x) => x.recordId}</span>
10
- `)}
11
- </div>
12
- <div class="review-filter">
13
- <${prefix}-text-field
14
- value=${sync((x) => x.filterText, 'string', 'input')}
15
- placeholder="Filter fields..."
16
- class="review-filter-input"
17
- data-test-id="review-filter-input"
18
- ></${prefix}-text-field>
19
- </div>
20
- <div class="review-body">
21
- ${repeat((x) => x.filteredSections, html `
22
- ${when((section) => section.fields.length > 0, html `
23
- <div class="review-section-header">${(section) => { var _a; return (_a = section.title) !== null && _a !== void 0 ? _a : '—'; }}</div>
24
- ${repeat((section) => section.fields, html `
25
- <div class="review-field">
26
- <span class="review-field-label">${(field) => field.label}</span>
27
- <span class="review-field-value">${(field) => field.value}</span>
28
- </div>
29
- `)}
30
- `)}
31
- `)}
32
- </div>
33
- </template>
34
- `;
35
- /** @internal */
36
- export const foundationFormReviewTemplate = html `
37
- ${(x) => getPrefixedReview(x.prefix)}
38
- `;
@@ -1,269 +0,0 @@
1
- import { __awaiter } from "tslib";
2
- import { getDatasource } from '@genesislcap/foundation-comms';
3
- import { CriteriaBuilder, ExpressionBuilder } from '@genesislcap/foundation-criteria';
4
- import { capitalCase } from 'change-case';
5
- /**
6
- * Flattens `buildReviewSections` output into a single ordered list.
7
- * Section titles are prepended to field labels as "Title — Field".
8
- */
9
- export function buildReviewFields(data, uiSchema, schema) {
10
- return __awaiter(this, void 0, void 0, function* () {
11
- const sections = yield buildReviewSections(data, uiSchema, schema);
12
- return sections.flatMap((section) => section.fields.map((field) => ({
13
- label: section.title ? `${section.title} — ${field.label}` : field.label,
14
- value: field.value,
15
- })));
16
- });
17
- }
18
- /**
19
- * Builds the review panel's fields grouped into sections by their nearest `Group` layout.
20
- * Ungrouped fields are collected into a single section with a `null` title (rendered with
21
- * a placeholder heading). Falls back to a flat, single ungrouped section when no UI schema
22
- * is available.
23
- *
24
- * Async because connected-select fields backed by `options.allOptionsResourceName` (rather
25
- * than a static `options.data`) resolve their display label with a criteria-filtered fetch
26
- * — see `resolveResourceOptionLabel`. The UI schema is walked synchronously to collect one
27
- * value-resolution promise per field (preserving encounter order), then all promises settle
28
- * in parallel via `Promise.all` before fields are added to their sections — so a slow fetch
29
- * for one field can't reorder fields that resolved faster.
30
- */
31
- export function buildReviewSections(data, uiSchema, schema) {
32
- return __awaiter(this, void 0, void 0, function* () {
33
- const sections = [];
34
- const sectionsByTitle = new Map();
35
- const addField = (title, field) => {
36
- let section = sectionsByTitle.get(title);
37
- if (!section) {
38
- section = { title, fields: [] };
39
- sectionsByTitle.set(title, section);
40
- sections.push(section);
41
- }
42
- section.fields.push(field);
43
- };
44
- const resolveDisplayValue = (raw, fieldName, options) => __awaiter(this, void 0, void 0, function* () {
45
- var _a, _b, _c;
46
- const displayValue = (_c = (_b = (_a = resolveOptionLabel(raw, options)) !== null && _a !== void 0 ? _a : (yield resolveResourceOptionLabel(raw, options))) !== null && _b !== void 0 ? _b : resolveEnumLabel(raw, fieldName, schema)) !== null && _c !== void 0 ? _c : raw;
47
- return formatValueForReview(displayValue);
48
- });
49
- const collect = (element, groupTitle) => {
50
- var _a, _b, _c;
51
- if (!element)
52
- return [];
53
- if (element.type === 'Control' && element.scope) {
54
- if ((_a = element.options) === null || _a === void 0 ? void 0 : _a.hidden)
55
- return [];
56
- const match = element.scope.match(/^#\/properties\/(.+)$/);
57
- if (!match)
58
- return [];
59
- const fieldName = match[1];
60
- const raw = getDataValueAtPath(data, fieldName);
61
- if (raw === undefined ||
62
- raw === null ||
63
- raw === '' ||
64
- (Array.isArray(raw) && raw.length === 0))
65
- return [];
66
- const shortName = fieldName.split('/properties/').pop();
67
- const fieldLabel = element.label || capitalCase(shortName);
68
- return [
69
- {
70
- groupTitle,
71
- label: fieldLabel,
72
- valuePromise: resolveDisplayValue(raw, fieldName, element.options),
73
- },
74
- ];
75
- }
76
- const nextGroup = element.type === 'Group' && element.label ? element.label : groupTitle;
77
- const children = (_b = element.elements) !== null && _b !== void 0 ? _b : (_c = element.options) === null || _c === void 0 ? void 0 : _c.childElements;
78
- return children ? children.flatMap((child) => collect(child, nextGroup)) : [];
79
- };
80
- if (uiSchema) {
81
- const pending = collect(uiSchema, null);
82
- const values = yield Promise.all(pending.map((field) => field.valuePromise));
83
- pending.forEach((field, index) => {
84
- addField(field.groupTitle, { label: field.label, value: values[index] });
85
- });
86
- }
87
- else {
88
- for (const [key, raw] of Object.entries(data !== null && data !== void 0 ? data : {})) {
89
- if (raw === undefined || raw === null || raw === '')
90
- continue;
91
- addField(null, { label: capitalCase(key), value: formatValueForReview(raw) });
92
- }
93
- }
94
- return sections;
95
- });
96
- }
97
- /**
98
- * Filters review sections down to fields whose label or value contains `query`
99
- * (case-insensitive). Sections left with no matching fields are dropped entirely.
100
- * Returns `sections` unchanged when `query` is blank.
101
- */
102
- export function filterReviewSections(sections, query) {
103
- const normalized = query.trim().toLowerCase();
104
- if (!normalized)
105
- return sections;
106
- return sections
107
- .map((section) => ({
108
- title: section.title,
109
- fields: section.fields.filter((field) => field.label.toLowerCase().includes(normalized) ||
110
- field.value.toLowerCase().includes(normalized)),
111
- }))
112
- .filter((section) => section.fields.length > 0);
113
- }
114
- /**
115
- * Recursively walks a UI schema element, collecting visible Control fields into `out`.
116
- * Passes the nearest Group label down so children are labelled "Group — Field".
117
- */
118
- export function collectReviewFields(element, data, out, groupLabel, schema) {
119
- var _a, _b, _c, _d, _e;
120
- if (element.type === 'Control' && element.scope) {
121
- if ((_a = element.options) === null || _a === void 0 ? void 0 : _a.hidden)
122
- return;
123
- const match = element.scope.match(/^#\/properties\/(.+)$/);
124
- if (!match)
125
- return;
126
- const fieldName = match[1];
127
- const raw = getDataValueAtPath(data, fieldName);
128
- if (raw === undefined || raw === null || raw === '' || (Array.isArray(raw) && raw.length === 0))
129
- return;
130
- const shortName = fieldName.split('/properties/').pop();
131
- const fieldLabel = element.label || capitalCase(shortName);
132
- const displayValue = (_c = (_b = resolveOptionLabel(raw, element.options)) !== null && _b !== void 0 ? _b : resolveEnumLabel(raw, fieldName, schema)) !== null && _c !== void 0 ? _c : raw;
133
- out.push({
134
- label: groupLabel ? `${groupLabel} — ${fieldLabel}` : fieldLabel,
135
- value: formatValueForReview(displayValue),
136
- });
137
- return;
138
- }
139
- const nextGroup = element.type === 'Group' && element.label ? element.label : groupLabel;
140
- const children = (_d = element.elements) !== null && _d !== void 0 ? _d : (_e = element.options) === null || _e === void 0 ? void 0 : _e.childElements;
141
- if (children) {
142
- for (const child of children) {
143
- collectReviewFields(child, data, out, nextGroup, schema);
144
- }
145
- }
146
- }
147
- /**
148
- * Looks up the display label for a raw value from `options.data` (used by segmented,
149
- * radio group, connected-select, and enum-with-explicit-data renderers). Honors
150
- * `options.valueField`/`options.labelField` when set, defaulting to `value`/`label`.
151
- * Returns `null` when no match found.
152
- */
153
- export function resolveOptionLabel(raw, options) {
154
- var _a, _b, _c;
155
- if (!Array.isArray(options === null || options === void 0 ? void 0 : options.data))
156
- return null;
157
- const valueKey = (_a = options.valueField) !== null && _a !== void 0 ? _a : 'value';
158
- const labelKey = (_b = options.labelField) !== null && _b !== void 0 ? _b : 'label';
159
- const entry = options.data.find((item) => item[valueKey] === raw);
160
- return (_c = entry === null || entry === void 0 ? void 0 : entry[labelKey]) !== null && _c !== void 0 ? _c : null;
161
- }
162
- /**
163
- * Resolves the display label for a connected-select field backed by
164
- * `options.allOptionsResourceName` (a Data Server/Request Server resource) rather than a
165
- * static `options.data` array — e.g. `ConnectedSelectControlRenderer` in async/remote mode.
166
- * Fetches a single row via a criteria-filtered snapshot matching `valueField === raw`,
167
- * then reads `labelField` off the returned row. Returns `null` when there's no resource
168
- * to query, the resource can't be reached, or no row matches.
169
- */
170
- export function resolveResourceOptionLabel(raw, options) {
171
- return __awaiter(this, void 0, void 0, function* () {
172
- var _a, _b, _c, _d;
173
- const resourceName = options === null || options === void 0 ? void 0 : options.allOptionsResourceName;
174
- if (!resourceName || raw === undefined || raw === null || raw === '')
175
- return null;
176
- const valueField = (_a = options.valueField) !== null && _a !== void 0 ? _a : 'value';
177
- const labelField = (_b = options.labelField) !== null && _b !== void 0 ? _b : 'label';
178
- const datasource = getDatasource();
179
- try {
180
- const criteria = new CriteriaBuilder()
181
- .withExpression(new ExpressionBuilder().withField(valueField).withValue(raw).build())
182
- .build();
183
- const initialized = yield datasource.init(Object.assign(Object.assign({}, options.datasourceConfig), { resourceName,
184
- criteria, isSnapshot: true, maxRows: 1, fields: valueField === labelField ? valueField : `${valueField} ${labelField}` }));
185
- if (!initialized)
186
- return null;
187
- const rows = yield datasource.snapshotFiltered();
188
- return (_d = (_c = rows === null || rows === void 0 ? void 0 : rows[0]) === null || _c === void 0 ? void 0 : _c[labelField]) !== null && _d !== void 0 ? _d : null;
189
- }
190
- catch (_e) {
191
- return null;
192
- }
193
- finally {
194
- datasource.destroy();
195
- }
196
- });
197
- }
198
- /**
199
- * For plain enum combobox fields (no options.data), applies the same `capitalCase`
200
- * transform the renderer uses — e.g. `SEMI_ANNUAL` → `Semi Annual`.
201
- * Navigates the JSON schema via the fieldName path to confirm the field is an enum
202
- * before transforming. Returns `null` for non-enum fields.
203
- */
204
- export function resolveEnumLabel(raw, fieldName, schema) {
205
- var _a, _b, _c, _d;
206
- if (typeof raw !== 'string')
207
- return null;
208
- if (!(schema === null || schema === void 0 ? void 0 : schema.properties))
209
- return null;
210
- let fieldSchema = schema;
211
- for (const part of fieldName.split('/properties/')) {
212
- fieldSchema = (_a = fieldSchema === null || fieldSchema === void 0 ? void 0 : fieldSchema.properties) === null || _a === void 0 ? void 0 : _a[part];
213
- }
214
- if (!fieldSchema)
215
- return null;
216
- // Matches plain `enum: [...]` or nullable `oneOf: [{ enum: [...] }, { type: 'null' }]`
217
- const enumValues = (_b = fieldSchema.enum) !== null && _b !== void 0 ? _b : (_d = (_c = fieldSchema.oneOf) === null || _c === void 0 ? void 0 : _c.find((x) => x.enum)) === null || _d === void 0 ? void 0 : _d.enum;
218
- if (Array.isArray(enumValues) && enumValues.includes(raw)) {
219
- return capitalCase(raw);
220
- }
221
- return null;
222
- }
223
- /**
224
- * Navigates a `/properties/`-separated path in data to support nested object scopes
225
- * such as `ADDRESS/properties/STREET` produced by Group layout UI schemas.
226
- */
227
- export function getDataValueAtPath(data, fieldName) {
228
- return navigateSegments(data, fieldName.split('/properties/'));
229
- }
230
- /** Core traversal — walks `data` one property key at a time. */
231
- function navigateSegments(data, segments) {
232
- let value = data;
233
- for (const segment of segments) {
234
- if (value == null)
235
- return undefined;
236
- value = value[segment];
237
- }
238
- return value;
239
- }
240
- /**
241
- * Converts a raw field value to a display string for the review panel.
242
- * Arrays of primitives are comma-joined; arrays of objects and plain objects
243
- * are rendered as readable `key: value` lines.
244
- */
245
- export function formatValueForReview(value) {
246
- if (Array.isArray(value)) {
247
- if (value.length === 0)
248
- return '';
249
- if (value.every((v) => v === null || typeof v !== 'object')) {
250
- return value.join(', ');
251
- }
252
- return value
253
- .map((item, i) => {
254
- const pairs = Object.entries(item !== null && item !== void 0 ? item : {})
255
- .filter(([, v]) => v !== null && v !== undefined && v !== '')
256
- .map(([k, v]) => `${k}: ${v}`)
257
- .join(', ');
258
- return `[${i + 1}] ${pairs}`;
259
- })
260
- .join('\n');
261
- }
262
- if (typeof value === 'object') {
263
- return Object.entries(value)
264
- .filter(([, v]) => v !== null && v !== undefined && v !== '')
265
- .map(([k, v]) => `${k}: ${v}`)
266
- .join(', ');
267
- }
268
- return String(value);
269
- }