@genesislcap/foundation-forms 14.396.4 → 14.397.1-alpha-87a7828.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 (60) hide show
  1. package/dist/custom-elements.json +565 -241
  2. package/dist/dts/form.d.ts +100 -1
  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/jsonforms/json-forms.d.ts +13 -0
  7. package/dist/dts/jsonforms/json-forms.d.ts.map +1 -1
  8. package/dist/dts/jsonforms/renderers/ArrayListWrapperRenderer.d.ts +5 -0
  9. package/dist/dts/jsonforms/renderers/ArrayListWrapperRenderer.d.ts.map +1 -1
  10. package/dist/dts/types.d.ts +88 -1
  11. package/dist/dts/types.d.ts.map +1 -1
  12. package/dist/dts/utils/csv-parser.d.ts +82 -0
  13. package/dist/dts/utils/csv-parser.d.ts.map +1 -0
  14. package/dist/dts/utils/index.d.ts +1 -0
  15. package/dist/dts/utils/index.d.ts.map +1 -1
  16. package/dist/dts/utils/schema-utils.d.ts +46 -0
  17. package/dist/dts/utils/schema-utils.d.ts.map +1 -0
  18. package/dist/dts/utils/validation.d.ts +2 -0
  19. package/dist/dts/utils/validation.d.ts.map +1 -1
  20. package/dist/esm/form.js +421 -5
  21. package/dist/esm/form.styles.js +38 -1
  22. package/dist/esm/form.template.js +33 -1
  23. package/dist/esm/jsonforms/json-forms.js +30 -0
  24. package/dist/esm/jsonforms/renderers/ArrayListWrapperRenderer.js +207 -13
  25. package/dist/esm/utils/csv-parser.js +458 -0
  26. package/dist/esm/utils/index.js +1 -0
  27. package/dist/esm/utils/schema-utils.js +120 -0
  28. package/dist/esm/utils/validation.js +2 -0
  29. package/dist/foundation-forms.api.json +1006 -29
  30. package/dist/foundation-forms.d.ts +281 -1
  31. package/docs/api/foundation-forms.arrayrendereroptions.md +2 -2
  32. package/docs/api/foundation-forms.bulkrowstatus.md +22 -0
  33. package/docs/api/foundation-forms.bulkrowsubmitstatus.md +13 -0
  34. package/docs/api/foundation-forms.bulksubmitfaileditem.md +20 -0
  35. package/docs/api/foundation-forms.bulksubmitresult.md +18 -0
  36. package/docs/api/foundation-forms.bulksubmitsuccessitem.md +17 -0
  37. package/docs/api/foundation-forms.childuischemaresolver.md +15 -0
  38. package/docs/api/foundation-forms.csvmappingresult.mappedrows.md +13 -0
  39. package/docs/api/foundation-forms.csvmappingresult.md +77 -0
  40. package/docs/api/foundation-forms.csvmappingresult.unmappedcolumns.md +13 -0
  41. package/docs/api/foundation-forms.csvparseresult.errors.md +13 -0
  42. package/docs/api/foundation-forms.csvparseresult.headers.md +13 -0
  43. package/docs/api/foundation-forms.csvparseresult.md +96 -0
  44. package/docs/api/foundation-forms.csvparseresult.rows.md +13 -0
  45. package/docs/api/foundation-forms.downloadcsvtemplate.md +74 -0
  46. package/docs/api/foundation-forms.form.bulkinsert.md +13 -0
  47. package/docs/api/foundation-forms.form.bulkinsertmaxitems.md +13 -0
  48. package/docs/api/foundation-forms.form.bulkinsertminitems.md +13 -0
  49. package/docs/api/foundation-forms.form.clearrowsubmitstatuses.md +17 -0
  50. package/docs/api/foundation-forms.form.downloadcsvtemplate.md +17 -0
  51. package/docs/api/foundation-forms.form.handlecsvfileselected.md +54 -0
  52. package/docs/api/foundation-forms.form.md +132 -0
  53. package/docs/api/foundation-forms.form.rowsubmitstatuses.md +13 -0
  54. package/docs/api/foundation-forms.form.submitsinglerow.md +56 -0
  55. package/docs/api/foundation-forms.generatecsvtemplate.md +104 -0
  56. package/docs/api/foundation-forms.mapcsvtoschema.md +72 -0
  57. package/docs/api/foundation-forms.md +147 -0
  58. package/docs/api/foundation-forms.parsecsv.md +56 -0
  59. package/docs/api-report.md.api.md +85 -3
  60. package/package.json +19 -17
@@ -3,6 +3,13 @@ import { Generate, composePaths, createDefaultValue } from '@jsonforms/core';
3
3
  import { designUnit } from '@microsoft/fast-components';
4
4
  import { html, css, observable, customElement, FASTElement, repeat, } from '@microsoft/fast-element';
5
5
  import { logger } from '../../utils';
6
+ const resolveRowUiSchema = (childUiSchema, index, rowData, formData, fallback) => {
7
+ if (typeof childUiSchema === 'function') {
8
+ const result = childUiSchema(index, rowData, formData);
9
+ return result !== null && result !== void 0 ? result : fallback;
10
+ }
11
+ return fallback;
12
+ };
6
13
  const isDeleteButtonHidden = (ctx) => {
7
14
  var _a, _b, _c;
8
15
  const canDeleteFn = (_a = ctx.parent.control.uischema.options) === null || _a === void 0 ? void 0 : _a.canDelete;
@@ -13,25 +20,71 @@ const isDeleteButtonHidden = (ctx) => {
13
20
  const controlData = formData[ctx.parent.control.path] && formData[ctx.parent.control.path][ctx.index];
14
21
  return !canDeleteFn(controlData);
15
22
  };
23
+ const getRowStatus = (ctx) => {
24
+ var _a;
25
+ const statuses = (_a = ctx.parent.form.jsonforms) === null || _a === void 0 ? void 0 : _a.rowSubmitStatuses;
26
+ return statuses === null || statuses === void 0 ? void 0 : statuses.get(ctx.index);
27
+ };
28
+ const isRowInStatus = (ctx, targetStatus) => {
29
+ const rowStatus = getRowStatus(ctx);
30
+ return (rowStatus === null || rowStatus === void 0 ? void 0 : rowStatus.status) === targetStatus;
31
+ };
32
+ const isRowDisabled = (ctx) => isRowInStatus(ctx, 'success');
33
+ const isRowSubmitting = (ctx) => isRowInStatus(ctx, 'submitting');
16
34
  export const ArrayListWrapperRendererTemplate = (prefix = 'zero') => html `
17
35
  <template>
18
36
  ${repeat((x) => Array(x.control.data), html `
19
- <div class="array-list">
37
+ <div class="array-list ${(x, ctx) => {
38
+ const rowStatus = getRowStatus(ctx);
39
+ return rowStatus ? `row-status-${rowStatus.status}` : '';
40
+ }}"
41
+ data-row-index="${(x, ctx) => ctx.index}"
42
+ >
43
+ <div class="row-status-indicator">
44
+ <${prefix}-progress-ring class="status-spinner"></${prefix}-progress-ring>
45
+ <${prefix}-icon name="check-circle" class="status-icon status-success"></${prefix}-icon>
46
+ <${prefix}-icon
47
+ name="times-circle"
48
+ class="status-icon status-failed"
49
+ title="${(x, ctx) => {
50
+ var _a;
51
+ const rowStatus = getRowStatus(ctx);
52
+ return ((_a = rowStatus === null || rowStatus === void 0 ? void 0 : rowStatus.errors) === null || _a === void 0 ? void 0 : _a.map((e) => e.TEXT).join(', ')) || 'Failed';
53
+ }}"
54
+ ></${prefix}-icon>
55
+ </div>
20
56
  <dispatch-renderer
21
57
  ?submitted=${(x, ctx) => ctx.parent.form.submitted}
22
58
  :dispatch=${(x, ctx) => ctx.parent.form.dispatch}
23
59
  :jsonforms=${(x, ctx) => ctx.parent.form.jsonforms}
24
60
  :prefix=${(x, ctx) => ctx.parent.form.prefix}
25
- :props=${(x, ctx) => ({
26
- uischema: ctx.parent.uiSchema,
27
- schema: ctx.parent.schema,
28
- renderers: ctx.parent.control.renderers,
29
- path: composePaths(ctx.parent.control.path, `${ctx.index}`),
30
- enabled: ctx.parent.control.enabled,
31
- })}
61
+ :props=${(x, ctx) => {
62
+ var _a, _b, _c, _d;
63
+ const childSchema = (_a = ctx.parent.control.uischema.options) === null || _a === void 0 ? void 0 : _a.childUiSchema;
64
+ const formData = (_c = (_b = ctx.parent.form.jsonforms) === null || _b === void 0 ? void 0 : _b.core) === null || _c === void 0 ? void 0 : _c.data;
65
+ const rowData = (_d = ctx.parent.control.data) === null || _d === void 0 ? void 0 : _d[ctx.index];
66
+ const uischema = resolveRowUiSchema(childSchema, ctx.index, rowData, formData, ctx.parent.uiSchema);
67
+ return {
68
+ uischema,
69
+ schema: ctx.parent.schema,
70
+ renderers: ctx.parent.control.renderers,
71
+ path: composePaths(ctx.parent.control.path, `${ctx.index}`),
72
+ enabled: ctx.parent.control.enabled && !isRowDisabled(ctx),
73
+ };
74
+ }}
32
75
  ></dispatch-renderer>
33
76
  <${prefix}-button
34
- ?hidden=${(x, ctx) => isDeleteButtonHidden(ctx)}
77
+ ?hidden=${(x, ctx) => { var _a; return !((_a = ctx.parent.form.jsonforms) === null || _a === void 0 ? void 0 : _a.bulkInsert) || isRowDisabled(ctx); }}
78
+ ?disabled=${(x, ctx) => isRowSubmitting(ctx)}
79
+ appearance="accent"
80
+ class="item-control-btn row-submit-btn"
81
+ data-test-id=${(x, ctx) => `${ctx.parent.control.path}-${ctx.index}-submit-item`}
82
+ @click=${(x, ctx) => ctx.parent.submitRow(ctx.index)}
83
+ >
84
+ <${prefix}-icon name="paper-plane"></${prefix}-icon>
85
+ </${prefix}-button>
86
+ <${prefix}-button
87
+ ?hidden=${(x, ctx) => isDeleteButtonHidden(ctx) || isRowDisabled(ctx)}
35
88
  appearance="lightweight"
36
89
  class="item-control-btn"
37
90
  data-test-id=${(x, ctx) => `${ctx.parent.control.path}-${ctx.index}-delete-item`}
@@ -56,27 +109,161 @@ export const ArrayListWrapperRendererTemplate = (prefix = 'zero') => html `
56
109
  const styles = css `
57
110
  :host {
58
111
  padding-left: calc(${designUnit} * 1px);
112
+ display: flex;
113
+ flex-direction: column;
114
+ gap: calc(${designUnit} * 3px);
115
+
116
+ /* Row status color tokens - can be overridden via CSS custom properties */
117
+ --row-status-success-color: var(--success-color, #28a745);
118
+ --row-status-failed-color: var(--error-color, #dc3545);
119
+ --row-status-submitting-color: var(--accent-fill-rest, #0078d4);
120
+
121
+ /* Array item card styling - industrial/utilitarian aesthetic */
122
+ --array-item-shadow: 0 1px 2px rgba(0, 0, 0, 0.04), 0 4px 8px rgba(0, 0, 0, 0.06);
123
+ --array-item-shadow-hover: 0 2px 4px rgba(0, 0, 0, 0.06), 0 6px 12px rgba(0, 0, 0, 0.08);
124
+ --array-item-border: 1px solid var(--neutral-stroke-rest, rgba(0, 0, 0, 0.12));
125
+ --array-item-radius: calc(${designUnit} * 2px);
59
126
  }
60
127
 
61
128
  .array-list {
129
+ display: flex;
130
+ align-items: flex-start;
131
+ position: relative;
132
+ padding: calc(${designUnit} * 2px) calc(${designUnit} * 3px);
133
+ padding-left: calc(${designUnit} * 2px + 3px); /* Extra space for left accent bar */
134
+ margin: 0;
135
+ background-color: var(--neutral-layer-1, #fff);
136
+ border: var(--array-item-border);
137
+ border-radius: var(--array-item-radius);
138
+ box-shadow: var(--array-item-shadow);
139
+ transition:
140
+ background-color 0.15s ease-in-out,
141
+ box-shadow 0.2s ease,
142
+ border-color 0.15s ease;
143
+ }
144
+
145
+ .array-list:hover {
146
+ box-shadow: var(--array-item-shadow-hover);
147
+ }
148
+
149
+ /* Content area grows to fill space; min-width prevents flex overflow */
150
+ .array-list > dispatch-renderer {
151
+ flex: 1;
152
+ min-width: 0;
153
+ }
154
+
155
+ /* Left accent bar for visual hierarchy - industrial form-slot feel */
156
+ .array-list::before {
157
+ content: '';
158
+ position: absolute;
159
+ left: 0;
160
+ top: 0;
161
+ bottom: 0;
162
+ width: 3px;
163
+ border-radius: var(--array-item-radius) 0 0 var(--array-item-radius);
164
+ background: var(--neutral-stroke-subtle, rgba(0, 0, 0, 0.06));
165
+ pointer-events: none;
166
+ }
167
+
168
+ .array-list.row-status-success::before {
169
+ background: var(--row-status-success-color);
170
+ }
171
+
172
+ .array-list.row-status-failed::before {
173
+ background: var(--row-status-failed-color);
174
+ }
175
+
176
+ .array-list.row-status-submitting::before {
177
+ background: var(--row-status-submitting-color);
178
+ }
179
+
180
+ .array-list.row-status-success {
181
+ background-color: color-mix(in srgb, var(--row-status-success-color), transparent 90%);
182
+ }
183
+
184
+ .array-list.row-status-failed {
185
+ background-color: color-mix(in srgb, var(--row-status-failed-color), transparent 90%);
186
+ }
187
+
188
+ .array-list.row-status-submitting {
189
+ background-color: color-mix(in srgb, var(--row-status-submitting-color), transparent 95%);
190
+ }
191
+
192
+ .row-status-indicator {
62
193
  display: flex;
63
194
  align-items: center;
195
+ justify-content: center;
196
+ min-width: calc(${designUnit} * 6px);
197
+ margin-right: calc(${designUnit} * 2px);
198
+ }
199
+
200
+ /* Hide all status indicators by default */
201
+ .row-status-indicator .status-spinner,
202
+ .row-status-indicator .status-success,
203
+ .row-status-indicator .status-failed {
204
+ display: none;
205
+ }
206
+
207
+ /* Show spinner when submitting */
208
+ .array-list.row-status-submitting .row-status-indicator .status-spinner {
209
+ display: flex;
210
+ }
211
+
212
+ /* Show success icon when successful */
213
+ .array-list.row-status-success .row-status-indicator .status-success {
214
+ display: flex;
215
+ }
216
+
217
+ /* Show failed icon when failed */
218
+ .array-list.row-status-failed .row-status-indicator .status-failed {
219
+ display: flex;
220
+ }
221
+
222
+ .status-icon {
223
+ width: calc(${designUnit} * 4px);
224
+ height: calc(${designUnit} * 4px);
225
+ }
226
+
227
+ .status-success {
228
+ color: var(--row-status-success-color);
229
+ }
230
+
231
+ .status-failed {
232
+ color: var(--row-status-failed-color);
233
+ cursor: help;
234
+ }
235
+
236
+ .status-spinner {
237
+ width: calc(${designUnit} * 4px);
238
+ height: calc(${designUnit} * 4px);
64
239
  }
65
240
 
66
241
  .item-control-btn {
67
- color: rgb(135, 155, 166);
68
- margin-left: 10px;
242
+ color: var(--neutral-foreground-hint, rgb(135, 155, 166));
243
+ margin-left: calc(${designUnit} * 2px);
69
244
  }
70
245
 
71
246
  .item-control-btn:hover {
72
247
  color: var(--accent-foreground-hover);
73
248
  }
249
+
250
+ .row-submit-btn {
251
+ min-width: calc(${designUnit} * 8px);
252
+ }
253
+
254
+ .row-submit-btn[disabled] {
255
+ opacity: 0.5;
256
+ cursor: not-allowed;
257
+ }
74
258
  `;
75
259
  let ArrayListWrapper = class ArrayListWrapper extends FASTElement {
76
260
  controlChanged() {
261
+ var _a;
77
262
  this.schema = this.control.schema;
78
- if (this.control.uischema.options) {
79
- this.uiSchema = this.control.uischema.options.childUiSchema;
263
+ const childUiSchema = (_a = this.control.uischema.options) === null || _a === void 0 ? void 0 : _a.childUiSchema;
264
+ // Only use static childUiSchema; when it's a function, resolve per-row in template
265
+ if (childUiSchema && typeof childUiSchema !== 'function') {
266
+ this.uiSchema = childUiSchema;
80
267
  return;
81
268
  }
82
269
  const arrayUiSchema = Generate.uiSchema(this.schema);
@@ -89,6 +276,13 @@ let ArrayListWrapper = class ArrayListWrapper extends FASTElement {
89
276
  deleteItem(index) {
90
277
  this.control.removeItems(this.control.path, [index])();
91
278
  }
279
+ /**
280
+ * Submits a single row by emitting an event that bubbles up to the foundation-form.
281
+ * @param index - The row index to submit
282
+ */
283
+ submitRow(index) {
284
+ this.$emit('submit-single-row', { index }, { bubbles: true, composed: true });
285
+ }
92
286
  };
93
287
  __decorate([
94
288
  observable