@ukiahinsure/a2ui-react-adapter 0.1.11 → 0.1.13
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.
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { A as A2UIClientAdapter, a as A2UISurfaceMetadata, b as A2UISessionController, c as A2UIRoomLike } from './session-
|
|
2
|
-
export { d as A2UIActionDeliveryStatus, e as A2UIActionResult, f as A2UIActionState, g as A2UICapabilityEnvelope, h as A2UIClientActionEnvelope, i as A2UIClientAdapterOptions, j as A2UIClientErrorEnvelope, k as A2UIClientErrorEvent, l as A2UIEditingSnapshot, m as A2UIFieldControl, n as A2UIFieldDescriptor, o as A2UIFieldInteractionField, p as A2UIFieldInteractionGroup, q as A2UIFieldValue, r as A2UIPendingAction, s as A2UIRendererActionEvent, t as A2UIServerEnvelope, u as A2UISessionControllerOptions, v as A2UISessionSnapshot, w as A2UISessionStatus, x as A2UIStreamParticipant, y as A2UISurfaceStructure, z as A2UITabDescriptor, B as A2UITrustedServerParticipant, C as A2UI_CAPABILITIES_TOPIC, D as A2UI_CLIENT_TOPIC, E as A2UI_PROTOCOL_VERSION, F as A2UI_SERVER_TOPIC, G as AckEnvelope, H as AckFieldError, I as AdapterSurface, J as CLIENT_ACTIONS, K as CLIENT_ERROR_CODES, L as ClientAction, M as ClientErrorCode, N as ENVELOPE_VERSION, O as MAX_ENVELOPE_BYTES, P as ParticipantRole, S as SectionNavigation, Q as SnapshotEnvelope, R as SurfaceUpdateEnvelope } from './session-
|
|
1
|
+
import { A as A2UIClientAdapter, a as A2UISurfaceMetadata, b as A2UISessionController, c as A2UIRoomLike } from './session-BcHSjUlD.js';
|
|
2
|
+
export { d as A2UIActionDeliveryStatus, e as A2UIActionResult, f as A2UIActionState, g as A2UICapabilityEnvelope, h as A2UIClientActionEnvelope, i as A2UIClientAdapterOptions, j as A2UIClientErrorEnvelope, k as A2UIClientErrorEvent, l as A2UIEditingSnapshot, m as A2UIFieldControl, n as A2UIFieldDescriptor, o as A2UIFieldInteractionField, p as A2UIFieldInteractionGroup, q as A2UIFieldValue, r as A2UIPendingAction, s as A2UIRendererActionEvent, t as A2UIServerEnvelope, u as A2UISessionControllerOptions, v as A2UISessionSnapshot, w as A2UISessionStatus, x as A2UIStreamParticipant, y as A2UISurfaceStructure, z as A2UITabDescriptor, B as A2UITrustedServerParticipant, C as A2UI_CAPABILITIES_TOPIC, D as A2UI_CLIENT_TOPIC, E as A2UI_PROTOCOL_VERSION, F as A2UI_SERVER_TOPIC, G as AckEnvelope, H as AckFieldError, I as AdapterSurface, J as CLIENT_ACTIONS, K as CLIENT_ERROR_CODES, L as ClientAction, M as ClientErrorCode, N as ENVELOPE_VERSION, O as MAX_ENVELOPE_BYTES, P as ParticipantRole, S as SectionNavigation, Q as SnapshotEnvelope, R as SurfaceUpdateEnvelope } from './session-BcHSjUlD.js';
|
|
3
3
|
import { ReactNode } from 'react';
|
|
4
4
|
|
|
5
5
|
/** Accessible host around the official A2UI v0.9.1 React surface. */
|
package/dist/index.js
CHANGED
|
@@ -30,6 +30,9 @@ var A2UIClientAdapter = class {
|
|
|
30
30
|
#structureBySurface = /* @__PURE__ */ new Map();
|
|
31
31
|
#persistedListRowsByPath = /* @__PURE__ */ new Map();
|
|
32
32
|
#deletedListItemIdsByPath = /* @__PURE__ */ new Map();
|
|
33
|
+
#stagedListRowUpdatesBySurface = /* @__PURE__ */ new Map();
|
|
34
|
+
#activeListRowEditsBySurface = /* @__PURE__ */ new Map();
|
|
35
|
+
#optimisticListRowsByPath = /* @__PURE__ */ new Map();
|
|
33
36
|
#version = 0;
|
|
34
37
|
#lastSeq = 0;
|
|
35
38
|
#disposed = false;
|
|
@@ -105,6 +108,38 @@ var A2UIClientAdapter = class {
|
|
|
105
108
|
}
|
|
106
109
|
return true;
|
|
107
110
|
}
|
|
111
|
+
stageListRowUpdate(surfaceId, values) {
|
|
112
|
+
this.#stagedListRowUpdatesBySurface.set(surfaceId, { ...values });
|
|
113
|
+
}
|
|
114
|
+
beginListRowEdit(surfaceId, rowKey, values) {
|
|
115
|
+
let edits = this.#activeListRowEditsBySurface.get(surfaceId);
|
|
116
|
+
if (edits === void 0) {
|
|
117
|
+
edits = /* @__PURE__ */ new Map();
|
|
118
|
+
this.#activeListRowEditsBySurface.set(surfaceId, edits);
|
|
119
|
+
}
|
|
120
|
+
edits.set(rowKey, { ...values });
|
|
121
|
+
}
|
|
122
|
+
updateListRowEdit(surfaceId, rowKey, values) {
|
|
123
|
+
const edits = this.#activeListRowEditsBySurface.get(surfaceId);
|
|
124
|
+
if (edits?.has(rowKey) !== true) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
edits.set(rowKey, { ...values });
|
|
128
|
+
}
|
|
129
|
+
getListRowEdit(surfaceId, rowKey) {
|
|
130
|
+
const values = this.#activeListRowEditsBySurface.get(surfaceId)?.get(rowKey);
|
|
131
|
+
return values === void 0 ? void 0 : { ...values };
|
|
132
|
+
}
|
|
133
|
+
clearListRowEdit(surfaceId, rowKey) {
|
|
134
|
+
const edits = this.#activeListRowEditsBySurface.get(surfaceId);
|
|
135
|
+
if (edits === void 0) {
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
edits.delete(rowKey);
|
|
139
|
+
if (edits.size === 0) {
|
|
140
|
+
this.#activeListRowEditsBySurface.delete(surfaceId);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
108
143
|
#dataModelValueForField(surfaceId, field, value) {
|
|
109
144
|
const descriptor = this.#fieldDescriptor(surfaceId, field);
|
|
110
145
|
if (descriptor?.control === "choice" && typeof value === "string" && value.length > 0) {
|
|
@@ -159,6 +194,8 @@ var A2UIClientAdapter = class {
|
|
|
159
194
|
this.#structureBySurface.clear();
|
|
160
195
|
this.#persistedListRowsByPath.clear();
|
|
161
196
|
this.#deletedListItemIdsByPath.clear();
|
|
197
|
+
this.#activeListRowEditsBySurface.clear();
|
|
198
|
+
this.#optimisticListRowsByPath.clear();
|
|
162
199
|
previous.model.dispose();
|
|
163
200
|
this.#notify();
|
|
164
201
|
}
|
|
@@ -198,6 +235,10 @@ var A2UIClientAdapter = class {
|
|
|
198
235
|
this.#disposed = true;
|
|
199
236
|
this.#processor.model.dispose();
|
|
200
237
|
this.#structureBySurface.clear();
|
|
238
|
+
this.#persistedListRowsByPath.clear();
|
|
239
|
+
this.#deletedListItemIdsByPath.clear();
|
|
240
|
+
this.#activeListRowEditsBySurface.clear();
|
|
241
|
+
this.#optimisticListRowsByPath.clear();
|
|
201
242
|
this.#listeners.clear();
|
|
202
243
|
this.#actionListeners.clear();
|
|
203
244
|
this.#errorListeners.clear();
|
|
@@ -216,7 +257,8 @@ var A2UIClientAdapter = class {
|
|
|
216
257
|
validated.data,
|
|
217
258
|
envelope.surfaceId,
|
|
218
259
|
this.#persistedListRowsByPath,
|
|
219
|
-
this.#deletedListItemIdsByPath
|
|
260
|
+
this.#deletedListItemIdsByPath,
|
|
261
|
+
this.#optimisticListRowsByPath
|
|
220
262
|
);
|
|
221
263
|
const listAddFreeMessages = removeListAddActionMessages(
|
|
222
264
|
rawMessages,
|
|
@@ -272,6 +314,8 @@ var A2UIClientAdapter = class {
|
|
|
272
314
|
if (envelope.kind === "snapshot") {
|
|
273
315
|
this.#persistedListRowsByPath.clear();
|
|
274
316
|
this.#deletedListItemIdsByPath.clear();
|
|
317
|
+
this.#activeListRowEditsBySurface.clear();
|
|
318
|
+
this.#optimisticListRowsByPath.clear();
|
|
275
319
|
}
|
|
276
320
|
rememberPersistedListRows(
|
|
277
321
|
this.#persistedListRowsByPath,
|
|
@@ -297,11 +341,18 @@ var A2UIClientAdapter = class {
|
|
|
297
341
|
);
|
|
298
342
|
return;
|
|
299
343
|
}
|
|
344
|
+
const stagedListRowUpdate = action.name === "flow.list.update" ? this.#stagedListRowUpdatesBySurface.get(action.surfaceId) : void 0;
|
|
345
|
+
if (stagedListRowUpdate !== void 0) {
|
|
346
|
+
this.#stagedListRowUpdatesBySurface.delete(action.surfaceId);
|
|
347
|
+
}
|
|
300
348
|
const event = {
|
|
301
349
|
actionName: action.name,
|
|
302
350
|
surfaceId: action.surfaceId,
|
|
303
351
|
sourceComponentId: action.sourceComponentId,
|
|
304
|
-
context: {
|
|
352
|
+
context: {
|
|
353
|
+
...action.context,
|
|
354
|
+
...stagedListRowUpdate ?? {}
|
|
355
|
+
}
|
|
305
356
|
};
|
|
306
357
|
const submittedProviderRow = submittedProviderRowFromEvent(event);
|
|
307
358
|
if (submittedProviderRow !== void 0) {
|
|
@@ -314,6 +365,9 @@ var A2UIClientAdapter = class {
|
|
|
314
365
|
if (event.actionName === "flow.list.delete") {
|
|
315
366
|
this.#removeDeletedListRow(event.surfaceId, event.context);
|
|
316
367
|
}
|
|
368
|
+
if (event.actionName === "flow.list.update") {
|
|
369
|
+
this.#updateListRow(event.surfaceId, event.context);
|
|
370
|
+
}
|
|
317
371
|
this.#options.onAction?.(event);
|
|
318
372
|
for (const listener of this.#actionListeners) {
|
|
319
373
|
listener(event);
|
|
@@ -348,6 +402,7 @@ var A2UIClientAdapter = class {
|
|
|
348
402
|
const cachedRows = this.#persistedListRowsByPath.get(listPath) ?? [];
|
|
349
403
|
const nextRows = removeListRowByItemId(cachedRows, itemId);
|
|
350
404
|
this.#persistedListRowsByPath.set(listPath, nextRows);
|
|
405
|
+
this.#optimisticListRowsByPath.get(listPath)?.delete(itemId);
|
|
351
406
|
rememberDeletedListItemId(this.#deletedListItemIdsByPath, listPath, itemId);
|
|
352
407
|
const surface = this.#processor.model.getSurface(surfaceId);
|
|
353
408
|
if (surface === void 0) {
|
|
@@ -360,6 +415,39 @@ var A2UIClientAdapter = class {
|
|
|
360
415
|
);
|
|
361
416
|
this.#notify();
|
|
362
417
|
}
|
|
418
|
+
#updateListRow(surfaceId, context) {
|
|
419
|
+
const listPath = context.listPath;
|
|
420
|
+
const itemId = context.itemId;
|
|
421
|
+
if (typeof listPath !== "string" || listPath.length === 0 || typeof itemId !== "string" || itemId.length === 0) {
|
|
422
|
+
return;
|
|
423
|
+
}
|
|
424
|
+
const cachedRows = this.#persistedListRowsByPath.get(listPath) ?? [];
|
|
425
|
+
const existingRow = cachedRows.find(
|
|
426
|
+
(candidate) => isRecord(candidate) && candidate.itemId === itemId
|
|
427
|
+
);
|
|
428
|
+
const row = updateListRowFromContext(context, existingRow);
|
|
429
|
+
if (row === void 0) {
|
|
430
|
+
return;
|
|
431
|
+
}
|
|
432
|
+
const rows = normalizeListRows(listPath, upsertListRow(cachedRows, row));
|
|
433
|
+
this.#persistedListRowsByPath.set(listPath, rows);
|
|
434
|
+
let optimisticRows = this.#optimisticListRowsByPath.get(listPath);
|
|
435
|
+
if (optimisticRows === void 0) {
|
|
436
|
+
optimisticRows = /* @__PURE__ */ new Map();
|
|
437
|
+
this.#optimisticListRowsByPath.set(listPath, optimisticRows);
|
|
438
|
+
}
|
|
439
|
+
optimisticRows.set(itemId, cloneJsonRecord(row));
|
|
440
|
+
const surface = this.#processor.model.getSurface(surfaceId);
|
|
441
|
+
if (surface === void 0) {
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
surface.dataModel.set(`/${listPath}`, cloneJsonArray(rows));
|
|
445
|
+
surface.dataModel.set(
|
|
446
|
+
`/${listPath.replaceAll(".", "/")}`,
|
|
447
|
+
cloneJsonArray(rows)
|
|
448
|
+
);
|
|
449
|
+
this.#notify();
|
|
450
|
+
}
|
|
363
451
|
#snapshotMessages() {
|
|
364
452
|
const messages = [];
|
|
365
453
|
for (const surface of this.#processor.model.surfacesMap.values()) {
|
|
@@ -859,8 +947,8 @@ function fieldFromPointer(path) {
|
|
|
859
947
|
function fieldPointer(field) {
|
|
860
948
|
return `/${field.replaceAll("~", "~0").replaceAll("/", "~1")}`;
|
|
861
949
|
}
|
|
862
|
-
function mergePersistedListRowsIntoMessages(messages, surfaceId, persistedRowsByPath, deletedItemIdsByPath) {
|
|
863
|
-
if (persistedRowsByPath.size === 0 && deletedItemIdsByPath.size === 0) {
|
|
950
|
+
function mergePersistedListRowsIntoMessages(messages, surfaceId, persistedRowsByPath, deletedItemIdsByPath, optimisticRowsByPath) {
|
|
951
|
+
if (persistedRowsByPath.size === 0 && deletedItemIdsByPath.size === 0 && optimisticRowsByPath.size === 0) {
|
|
864
952
|
return [...messages];
|
|
865
953
|
}
|
|
866
954
|
let mergedRoot = false;
|
|
@@ -876,7 +964,8 @@ function mergePersistedListRowsIntoMessages(messages, surfaceId, persistedRowsBy
|
|
|
876
964
|
value: mergePersistedListRowsIntoRoot(
|
|
877
965
|
message.updateDataModel.value,
|
|
878
966
|
persistedRowsByPath,
|
|
879
|
-
deletedItemIdsByPath
|
|
967
|
+
deletedItemIdsByPath,
|
|
968
|
+
optimisticRowsByPath
|
|
880
969
|
)
|
|
881
970
|
}
|
|
882
971
|
};
|
|
@@ -894,26 +983,33 @@ function mergePersistedListRowsIntoMessages(messages, surfaceId, persistedRowsBy
|
|
|
894
983
|
value: mergePersistedListRowsIntoRoot(
|
|
895
984
|
{},
|
|
896
985
|
persistedRowsByPath,
|
|
897
|
-
deletedItemIdsByPath
|
|
986
|
+
deletedItemIdsByPath,
|
|
987
|
+
optimisticRowsByPath
|
|
898
988
|
)
|
|
899
989
|
}
|
|
900
990
|
}
|
|
901
991
|
];
|
|
902
992
|
}
|
|
903
|
-
function mergePersistedListRowsIntoRoot(root, persistedRowsByPath, deletedItemIdsByPath) {
|
|
993
|
+
function mergePersistedListRowsIntoRoot(root, persistedRowsByPath, deletedItemIdsByPath, optimisticRowsByPath) {
|
|
904
994
|
const merged = cloneJsonRecord(root);
|
|
905
995
|
for (const listPath of /* @__PURE__ */ new Set([
|
|
906
996
|
...persistedRowsByPath.keys(),
|
|
907
|
-
...deletedItemIdsByPath.keys()
|
|
997
|
+
...deletedItemIdsByPath.keys(),
|
|
998
|
+
...optimisticRowsByPath.keys()
|
|
908
999
|
])) {
|
|
909
1000
|
const rows = persistedRowsByPath.get(listPath) ?? [];
|
|
1001
|
+
const optimisticRows = optimisticRowsByPath.get(listPath);
|
|
910
1002
|
const dottedRows = merged[listPath];
|
|
911
1003
|
const nestedRows = getNestedValue(merged, listPath);
|
|
912
1004
|
const incomingRows = Array.isArray(dottedRows) ? dottedRows : Array.isArray(nestedRows) ? nestedRows : void 0;
|
|
913
1005
|
const shouldPreserveCachedRows = rows.length > 0 && (incomingRows === void 0 || incomingRows.length === 0 && (!hasListDraft(merged, listPath) || hasBlankListDraft(merged, listPath)));
|
|
914
1006
|
const effectiveRows = shouldPreserveCachedRows ? rows : incomingRows ?? rows;
|
|
915
|
-
const
|
|
1007
|
+
const optimisticEffectiveRows = mergeOptimisticListRows(
|
|
916
1008
|
effectiveRows,
|
|
1009
|
+
optimisticRows
|
|
1010
|
+
);
|
|
1011
|
+
const visibleRows = filterDeletedListRows(
|
|
1012
|
+
optimisticEffectiveRows,
|
|
917
1013
|
deletedItemIdsByPath.get(listPath)
|
|
918
1014
|
);
|
|
919
1015
|
const normalizedRows = normalizeListRows(listPath, visibleRows, merged);
|
|
@@ -949,6 +1045,16 @@ function isBlankDraftValue(value) {
|
|
|
949
1045
|
}
|
|
950
1046
|
return false;
|
|
951
1047
|
}
|
|
1048
|
+
function mergeOptimisticListRows(rows, optimisticRows) {
|
|
1049
|
+
if (optimisticRows === void 0 || optimisticRows.size === 0) {
|
|
1050
|
+
return cloneJsonArray(rows);
|
|
1051
|
+
}
|
|
1052
|
+
let merged = cloneJsonArray(rows);
|
|
1053
|
+
for (const row of optimisticRows.values()) {
|
|
1054
|
+
merged = upsertListRow(merged, cloneJsonRecord(row));
|
|
1055
|
+
}
|
|
1056
|
+
return merged;
|
|
1057
|
+
}
|
|
952
1058
|
function rememberPersistedListRows(persistedRowsByPath, deletedItemIdsByPath, root) {
|
|
953
1059
|
if (!isRecord(root)) {
|
|
954
1060
|
return;
|
|
@@ -1192,6 +1298,35 @@ function isProviderSubmitLabel(label) {
|
|
|
1192
1298
|
function normalizeFieldKey(key) {
|
|
1193
1299
|
return key.trim().toLowerCase().replaceAll(/[^a-z0-9]+/g, "_").replaceAll(/^_+|_+$/g, "");
|
|
1194
1300
|
}
|
|
1301
|
+
function updateListRowFromContext(context, existingRow) {
|
|
1302
|
+
const itemId = context.itemId;
|
|
1303
|
+
if (typeof itemId !== "string" || itemId.length === 0) {
|
|
1304
|
+
return void 0;
|
|
1305
|
+
}
|
|
1306
|
+
const row = isRecord(existingRow) ? cloneJsonRecord(existingRow) : {};
|
|
1307
|
+
row.itemId = itemId;
|
|
1308
|
+
let hasUpdate = false;
|
|
1309
|
+
for (const [key, value] of Object.entries(context)) {
|
|
1310
|
+
if (key === "listPath" || key === "itemId" || !isFieldValue(value)) {
|
|
1311
|
+
continue;
|
|
1312
|
+
}
|
|
1313
|
+
row[key] = value;
|
|
1314
|
+
hasUpdate = true;
|
|
1315
|
+
}
|
|
1316
|
+
if (!hasUpdate) {
|
|
1317
|
+
return void 0;
|
|
1318
|
+
}
|
|
1319
|
+
row.__displayText = listRowDisplayText(row);
|
|
1320
|
+
return row;
|
|
1321
|
+
}
|
|
1322
|
+
function listRowDisplayText(row) {
|
|
1323
|
+
return Object.entries(row).filter(([key, value]) => {
|
|
1324
|
+
if (key === "itemId" || key === "__displayText" || value === null) {
|
|
1325
|
+
return false;
|
|
1326
|
+
}
|
|
1327
|
+
return isFieldValue(value) && String(value).trim().length > 0;
|
|
1328
|
+
}).map(([key, value]) => `${key}: ${String(value).trim()}`).join(" | ");
|
|
1329
|
+
}
|
|
1195
1330
|
function upsertListRow(rows, row) {
|
|
1196
1331
|
const itemId = row.itemId;
|
|
1197
1332
|
if (typeof itemId !== "string" || itemId.length === 0) {
|
|
@@ -1500,7 +1635,7 @@ function A2UISurfaceHost({
|
|
|
1500
1635
|
validationSummaryId
|
|
1501
1636
|
),
|
|
1502
1637
|
formatFieldLabels(root),
|
|
1503
|
-
annotateSavedLoopTables(root),
|
|
1638
|
+
annotateSavedLoopTables(root, adapter, surface.id),
|
|
1504
1639
|
bindFieldInteractionGroups(
|
|
1505
1640
|
root,
|
|
1506
1641
|
resolvedSurfaceMetadata?.fieldInteractions ?? [],
|
|
@@ -2188,9 +2323,10 @@ function generatedFieldLabelName(text) {
|
|
|
2188
2323
|
const unwrapped = trimmed.startsWith("*") && trimmed.endsWith("*") ? trimmed.slice(1, -1).trim() : trimmed;
|
|
2189
2324
|
return /^[A-Za-z][A-Za-z0-9_]*$/.test(unwrapped) && /[_A-Z]/.test(unwrapped) ? unwrapped : void 0;
|
|
2190
2325
|
}
|
|
2191
|
-
function annotateSavedLoopTables(root) {
|
|
2326
|
+
function annotateSavedLoopTables(root, adapter, surfaceId) {
|
|
2192
2327
|
const originals = /* @__PURE__ */ new Map();
|
|
2193
2328
|
const textOriginals = /* @__PURE__ */ new Map();
|
|
2329
|
+
const listeners = [];
|
|
2194
2330
|
const remember = (element) => {
|
|
2195
2331
|
if (originals.has(element)) {
|
|
2196
2332
|
return;
|
|
@@ -2205,6 +2341,7 @@ function annotateSavedLoopTables(root) {
|
|
|
2205
2341
|
loopColumnCount: element.dataset.a2uiLoopColumnCount,
|
|
2206
2342
|
loopLabel: element.dataset.a2uiLoopLabel,
|
|
2207
2343
|
generatedHeader: element.dataset.a2uiLoopGeneratedHeader,
|
|
2344
|
+
actionControl: element.dataset.a2uiLoopActionControl,
|
|
2208
2345
|
hidden: element.getAttribute("hidden"),
|
|
2209
2346
|
ariaHidden: element.getAttribute("aria-hidden")
|
|
2210
2347
|
});
|
|
@@ -2215,6 +2352,10 @@ function annotateSavedLoopTables(root) {
|
|
|
2215
2352
|
}
|
|
2216
2353
|
element.textContent = text;
|
|
2217
2354
|
};
|
|
2355
|
+
const commitText = (element, text) => {
|
|
2356
|
+
textOriginals.set(element, text);
|
|
2357
|
+
element.textContent = text;
|
|
2358
|
+
};
|
|
2218
2359
|
const generatedElements = [];
|
|
2219
2360
|
const rows = [...root.querySelectorAll("div, section, article, li")].filter(
|
|
2220
2361
|
(row) => getSavedLoopRowFields(row).length > 0 && normalizedLoopSummaryFields(getSavedLoopSummaryFields(row)).length >= 2
|
|
@@ -2294,10 +2435,23 @@ function annotateSavedLoopTables(root) {
|
|
|
2294
2435
|
child.dataset.a2uiLoopColumn = String(Math.floor(columnIndex / 2) + 1);
|
|
2295
2436
|
columnIndex += 1;
|
|
2296
2437
|
}
|
|
2297
|
-
normalizeSavedLoopRow(
|
|
2438
|
+
normalizeSavedLoopRow(
|
|
2439
|
+
row,
|
|
2440
|
+
rowIndex,
|
|
2441
|
+
remember,
|
|
2442
|
+
setText,
|
|
2443
|
+
commitText,
|
|
2444
|
+
generatedElements,
|
|
2445
|
+
listeners,
|
|
2446
|
+
adapter,
|
|
2447
|
+
surfaceId
|
|
2448
|
+
);
|
|
2298
2449
|
});
|
|
2299
2450
|
}
|
|
2300
2451
|
return () => {
|
|
2452
|
+
for (const remove of listeners.reverse()) {
|
|
2453
|
+
remove();
|
|
2454
|
+
}
|
|
2301
2455
|
for (const [element, original] of originals) {
|
|
2302
2456
|
restoreDataset(element, "a2uiLoopTable", original.loopTable);
|
|
2303
2457
|
restoreDataset(element, "a2uiLoopRow", original.loopRow);
|
|
@@ -2312,6 +2466,7 @@ function annotateSavedLoopTables(root) {
|
|
|
2312
2466
|
"a2uiLoopGeneratedHeader",
|
|
2313
2467
|
original.generatedHeader
|
|
2314
2468
|
);
|
|
2469
|
+
restoreDataset(element, "a2uiLoopActionControl", original.actionControl);
|
|
2315
2470
|
restoreAttribute(element, "hidden", original.hidden);
|
|
2316
2471
|
restoreAttribute(element, "aria-hidden", original.ariaHidden);
|
|
2317
2472
|
}
|
|
@@ -2319,6 +2474,14 @@ function annotateSavedLoopTables(root) {
|
|
|
2319
2474
|
element.textContent = text;
|
|
2320
2475
|
}
|
|
2321
2476
|
for (const element of generatedElements) {
|
|
2477
|
+
if (element.dataset.a2uiGeneratedLoopActionCell === "true") {
|
|
2478
|
+
const parent = element.parentElement;
|
|
2479
|
+
if (parent !== null) {
|
|
2480
|
+
while (element.firstChild !== null) {
|
|
2481
|
+
parent.insertBefore(element.firstChild, element);
|
|
2482
|
+
}
|
|
2483
|
+
}
|
|
2484
|
+
}
|
|
2322
2485
|
element.remove();
|
|
2323
2486
|
}
|
|
2324
2487
|
};
|
|
@@ -2346,7 +2509,7 @@ function buildSavedLoopHeader(parent, firstRow) {
|
|
|
2346
2509
|
header.appendChild(action);
|
|
2347
2510
|
return header;
|
|
2348
2511
|
}
|
|
2349
|
-
function normalizeSavedLoopRow(row, rowIndex, remember, setText, generatedElements) {
|
|
2512
|
+
function normalizeSavedLoopRow(row, rowIndex, remember, setText, commitText, generatedElements, listeners, adapter, surfaceId) {
|
|
2350
2513
|
const summaryFields = normalizedLoopSummaryFields(getSavedLoopSummaryFields(row));
|
|
2351
2514
|
if (summaryFields.length < 2) {
|
|
2352
2515
|
return;
|
|
@@ -2356,6 +2519,7 @@ function normalizeSavedLoopRow(row, rowIndex, remember, setText, generatedElemen
|
|
|
2356
2519
|
const fields = [...row.querySelectorAll("[data-a2ui-loop-field='true']")];
|
|
2357
2520
|
const summaryValues = getSavedLoopSummaryValues(row);
|
|
2358
2521
|
const action = row.querySelector("[data-a2ui-loop-cell='action']");
|
|
2522
|
+
const save = row.querySelector("[data-a2ui-loop-cell='save']");
|
|
2359
2523
|
const orderedFields = summaryFields.slice(0, columnCount).map((fieldName) => {
|
|
2360
2524
|
const field = findSavedLoopField(fields, fieldName);
|
|
2361
2525
|
if (field !== void 0) {
|
|
@@ -2394,9 +2558,27 @@ function normalizeSavedLoopRow(row, rowIndex, remember, setText, generatedElemen
|
|
|
2394
2558
|
value.dataset.a2uiLoopCell = "value";
|
|
2395
2559
|
}
|
|
2396
2560
|
});
|
|
2561
|
+
const rowEditValues = savedLoopRowEditValues(orderedFields, summaryFields);
|
|
2562
|
+
const rowKey = savedLoopRowEditKey(rowIndex, summaryFields, rowEditValues);
|
|
2397
2563
|
if (action !== null) {
|
|
2398
2564
|
remember(action);
|
|
2399
2565
|
action.dataset.a2uiLoopColumn = String(columnCount + 1);
|
|
2566
|
+
createSavedLoopActionCell(
|
|
2567
|
+
row,
|
|
2568
|
+
save,
|
|
2569
|
+
action,
|
|
2570
|
+
columnCount + 1,
|
|
2571
|
+
remember,
|
|
2572
|
+
setText,
|
|
2573
|
+
commitText,
|
|
2574
|
+
generatedElements,
|
|
2575
|
+
listeners,
|
|
2576
|
+
adapter,
|
|
2577
|
+
surfaceId,
|
|
2578
|
+
rowKey,
|
|
2579
|
+
orderedFields,
|
|
2580
|
+
summaryFields.slice(0, columnCount)
|
|
2581
|
+
);
|
|
2400
2582
|
}
|
|
2401
2583
|
for (const field of fields) {
|
|
2402
2584
|
if (orderedFields.includes(field)) {
|
|
@@ -2408,6 +2590,202 @@ function normalizeSavedLoopRow(row, rowIndex, remember, setText, generatedElemen
|
|
|
2408
2590
|
field.setAttribute("aria-hidden", "true");
|
|
2409
2591
|
}
|
|
2410
2592
|
}
|
|
2593
|
+
function createSavedLoopActionCell(row, save, action, column, remember, setText, commitText, generatedElements, listeners, adapter, surfaceId, rowKey, orderedFields, summaryFields) {
|
|
2594
|
+
if (save === null) {
|
|
2595
|
+
return void 0;
|
|
2596
|
+
}
|
|
2597
|
+
remember(save);
|
|
2598
|
+
remember(action);
|
|
2599
|
+
const actionCell = row.ownerDocument.createElement("div");
|
|
2600
|
+
const editButton = row.ownerDocument.createElement("button");
|
|
2601
|
+
editButton.type = "button";
|
|
2602
|
+
actionCell.dataset.a2uiLoopCell = "action";
|
|
2603
|
+
actionCell.dataset.a2uiLoopColumn = String(column);
|
|
2604
|
+
actionCell.dataset.a2uiLoopActionGroup = "true";
|
|
2605
|
+
actionCell.dataset.a2uiGeneratedLoopActionCell = "true";
|
|
2606
|
+
editButton.dataset.a2uiLoopCell = "edit";
|
|
2607
|
+
editButton.dataset.a2uiLoopColumn = String(column);
|
|
2608
|
+
editButton.dataset.a2uiGeneratedLoopEditButton = "true";
|
|
2609
|
+
editButton.textContent = "Edit";
|
|
2610
|
+
row.insertBefore(actionCell, action);
|
|
2611
|
+
actionCell.append(editButton, save, action);
|
|
2612
|
+
save.dataset.a2uiLoopCell = "save";
|
|
2613
|
+
save.dataset.a2uiLoopColumn = String(column);
|
|
2614
|
+
save.setAttribute("hidden", "");
|
|
2615
|
+
save.setAttribute("aria-hidden", "true");
|
|
2616
|
+
action.dataset.a2uiLoopColumn = String(column);
|
|
2617
|
+
listeners.push(
|
|
2618
|
+
bindSavedLoopEditAction(
|
|
2619
|
+
editButton,
|
|
2620
|
+
save,
|
|
2621
|
+
row,
|
|
2622
|
+
orderedFields,
|
|
2623
|
+
summaryFields,
|
|
2624
|
+
adapter,
|
|
2625
|
+
surfaceId,
|
|
2626
|
+
rowKey,
|
|
2627
|
+
setText,
|
|
2628
|
+
commitText,
|
|
2629
|
+
generatedElements,
|
|
2630
|
+
listeners
|
|
2631
|
+
)
|
|
2632
|
+
);
|
|
2633
|
+
const activeEditValues = adapter.getListRowEdit(surfaceId, rowKey);
|
|
2634
|
+
if (activeEditValues !== void 0) {
|
|
2635
|
+
renderSavedLoopEditInputs(
|
|
2636
|
+
editButton,
|
|
2637
|
+
row,
|
|
2638
|
+
orderedFields,
|
|
2639
|
+
summaryFields,
|
|
2640
|
+
adapter,
|
|
2641
|
+
surfaceId,
|
|
2642
|
+
rowKey,
|
|
2643
|
+
setText,
|
|
2644
|
+
generatedElements,
|
|
2645
|
+
listeners,
|
|
2646
|
+
activeEditValues,
|
|
2647
|
+
false
|
|
2648
|
+
);
|
|
2649
|
+
}
|
|
2650
|
+
generatedElements.push(editButton);
|
|
2651
|
+
generatedElements.push(actionCell);
|
|
2652
|
+
delete action.dataset.a2uiLoopCell;
|
|
2653
|
+
delete action.dataset.a2uiLoopColumn;
|
|
2654
|
+
action.dataset.a2uiLoopActionControl = "true";
|
|
2655
|
+
return actionCell;
|
|
2656
|
+
}
|
|
2657
|
+
function bindSavedLoopEditAction(editButton, submitButton, row, orderedFields, summaryFields, adapter, surfaceId, rowKey, setText, commitText, generatedElements, listeners) {
|
|
2658
|
+
const onClick = (event) => {
|
|
2659
|
+
if (adapter.getListRowEdit(surfaceId, rowKey) === void 0) {
|
|
2660
|
+
event.preventDefault();
|
|
2661
|
+
event.stopImmediatePropagation();
|
|
2662
|
+
const values2 = savedLoopRowEditValues(orderedFields, summaryFields);
|
|
2663
|
+
adapter.beginListRowEdit(surfaceId, rowKey, values2);
|
|
2664
|
+
renderSavedLoopEditInputs(
|
|
2665
|
+
editButton,
|
|
2666
|
+
row,
|
|
2667
|
+
orderedFields,
|
|
2668
|
+
summaryFields,
|
|
2669
|
+
adapter,
|
|
2670
|
+
surfaceId,
|
|
2671
|
+
rowKey,
|
|
2672
|
+
setText,
|
|
2673
|
+
generatedElements,
|
|
2674
|
+
listeners,
|
|
2675
|
+
values2,
|
|
2676
|
+
true
|
|
2677
|
+
);
|
|
2678
|
+
return;
|
|
2679
|
+
}
|
|
2680
|
+
event.preventDefault();
|
|
2681
|
+
event.stopImmediatePropagation();
|
|
2682
|
+
const values = savedLoopRowInputValues(orderedFields, summaryFields);
|
|
2683
|
+
adapter.clearListRowEdit(surfaceId, rowKey);
|
|
2684
|
+
delete row.dataset.a2uiLoopEditing;
|
|
2685
|
+
setText(editButton, "Edit");
|
|
2686
|
+
orderedFields.forEach((field, index) => {
|
|
2687
|
+
const fieldName = summaryFields[index];
|
|
2688
|
+
const value = field.querySelector(
|
|
2689
|
+
"[data-a2ui-loop-cell='value']"
|
|
2690
|
+
);
|
|
2691
|
+
if (fieldName !== void 0 && value !== null) {
|
|
2692
|
+
commitText(value, stringEditValue(values[fieldName]));
|
|
2693
|
+
}
|
|
2694
|
+
});
|
|
2695
|
+
adapter.stageListRowUpdate(surfaceId, values);
|
|
2696
|
+
window.setTimeout(() => {
|
|
2697
|
+
const clickable = submitButton instanceof HTMLButtonElement ? submitButton : submitButton.querySelector("button");
|
|
2698
|
+
(clickable ?? submitButton).click();
|
|
2699
|
+
}, 0);
|
|
2700
|
+
};
|
|
2701
|
+
editButton.addEventListener("click", onClick, { capture: true });
|
|
2702
|
+
return () => {
|
|
2703
|
+
editButton.removeEventListener("click", onClick, { capture: true });
|
|
2704
|
+
};
|
|
2705
|
+
}
|
|
2706
|
+
function renderSavedLoopEditInputs(editButton, row, orderedFields, summaryFields, adapter, surfaceId, rowKey, setText, generatedElements, listeners, values, focusFirstInput) {
|
|
2707
|
+
row.dataset.a2uiLoopEditing = "true";
|
|
2708
|
+
for (const [index, field] of orderedFields.entries()) {
|
|
2709
|
+
const fieldName = summaryFields[index];
|
|
2710
|
+
const value = field.querySelector(
|
|
2711
|
+
"[data-a2ui-loop-cell='value']"
|
|
2712
|
+
);
|
|
2713
|
+
if (fieldName === void 0 || value === null) {
|
|
2714
|
+
continue;
|
|
2715
|
+
}
|
|
2716
|
+
let input = value.querySelector(
|
|
2717
|
+
"input[data-a2ui-loop-edit-input='true']"
|
|
2718
|
+
);
|
|
2719
|
+
if (input === null) {
|
|
2720
|
+
input = row.ownerDocument.createElement("input");
|
|
2721
|
+
input.type = "text";
|
|
2722
|
+
input.name = fieldName;
|
|
2723
|
+
input.setAttribute("aria-label", displayFieldLabel(fieldName));
|
|
2724
|
+
input.dataset.a2uiLoopEditInput = "true";
|
|
2725
|
+
setText(value, "");
|
|
2726
|
+
value.appendChild(input);
|
|
2727
|
+
generatedElements.push(input);
|
|
2728
|
+
}
|
|
2729
|
+
input.value = stringEditValue(values[fieldName]);
|
|
2730
|
+
const syncEditValue = () => {
|
|
2731
|
+
adapter.updateListRowEdit(
|
|
2732
|
+
surfaceId,
|
|
2733
|
+
rowKey,
|
|
2734
|
+
savedLoopRowInputValues(orderedFields, summaryFields)
|
|
2735
|
+
);
|
|
2736
|
+
};
|
|
2737
|
+
input.addEventListener("input", syncEditValue);
|
|
2738
|
+
input.addEventListener("change", syncEditValue);
|
|
2739
|
+
listeners.push(() => {
|
|
2740
|
+
input.removeEventListener("input", syncEditValue);
|
|
2741
|
+
input.removeEventListener("change", syncEditValue);
|
|
2742
|
+
});
|
|
2743
|
+
}
|
|
2744
|
+
setText(editButton, "Save");
|
|
2745
|
+
if (focusFirstInput) {
|
|
2746
|
+
row.querySelector(
|
|
2747
|
+
"input[data-a2ui-loop-edit-input='true']"
|
|
2748
|
+
)?.focus();
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
function savedLoopRowEditValues(orderedFields, summaryFields) {
|
|
2752
|
+
const values = {};
|
|
2753
|
+
orderedFields.forEach((field, index) => {
|
|
2754
|
+
const fieldName = summaryFields[index];
|
|
2755
|
+
const value = field.querySelector(
|
|
2756
|
+
"[data-a2ui-loop-cell='value']"
|
|
2757
|
+
);
|
|
2758
|
+
if (fieldName !== void 0) {
|
|
2759
|
+
values[fieldName] = value?.textContent?.trim() ?? "";
|
|
2760
|
+
}
|
|
2761
|
+
});
|
|
2762
|
+
return values;
|
|
2763
|
+
}
|
|
2764
|
+
function savedLoopRowInputValues(orderedFields, summaryFields) {
|
|
2765
|
+
const values = {};
|
|
2766
|
+
orderedFields.forEach((field, index) => {
|
|
2767
|
+
const fieldName = summaryFields[index];
|
|
2768
|
+
const input = field.querySelector(
|
|
2769
|
+
"input[data-a2ui-loop-edit-input='true']"
|
|
2770
|
+
);
|
|
2771
|
+
const value = field.querySelector(
|
|
2772
|
+
"[data-a2ui-loop-cell='value']"
|
|
2773
|
+
);
|
|
2774
|
+
if (fieldName !== void 0) {
|
|
2775
|
+
values[fieldName] = input?.value ?? value?.textContent?.trim() ?? "";
|
|
2776
|
+
}
|
|
2777
|
+
});
|
|
2778
|
+
return values;
|
|
2779
|
+
}
|
|
2780
|
+
function savedLoopRowEditKey(rowIndex, summaryFields, values) {
|
|
2781
|
+
return `${rowIndex}:${summaryFields.map((field) => `${field}=${stringEditValue(values[field])}`).join("|")}`;
|
|
2782
|
+
}
|
|
2783
|
+
function stringEditValue(value) {
|
|
2784
|
+
if (value === null || value === void 0) {
|
|
2785
|
+
return "";
|
|
2786
|
+
}
|
|
2787
|
+
return String(value);
|
|
2788
|
+
}
|
|
2411
2789
|
function findSavedLoopField(fields, summaryField) {
|
|
2412
2790
|
const expectedName = canonicalLoopFieldName(summaryField).toLowerCase();
|
|
2413
2791
|
const expectedLabel = displayFieldLabel(expectedName).toLowerCase();
|