@wildwinter/app-shell 0.56.0 → 0.57.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.
- package/README.md +20 -0
- package/dist/controls.css +52 -0
- package/dist/controls.css.map +1 -1
- package/dist/index.cjs +22 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +15 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.js +22 -1
- package/dist/index.js.map +1 -1
- package/dist/value-rows.cjs +200 -10
- package/dist/value-rows.cjs.map +1 -1
- package/dist/value-rows.d.cts +36 -1
- package/dist/value-rows.d.ts +36 -1
- package/dist/value-rows.js +197 -12
- package/dist/value-rows.js.map +1 -1
- package/package.json +1 -1
package/dist/value-rows.d.cts
CHANGED
|
@@ -50,6 +50,41 @@ declare function foldCaption(name: string, set: number): string;
|
|
|
50
50
|
*/
|
|
51
51
|
declare function extensionFold(): ExtensionFold;
|
|
52
52
|
|
|
53
|
+
/** A map whose values are records: edited in the grid, summarised in the inspector. */
|
|
54
|
+
declare function isRecordMap(decl: ValueDecl): boolean;
|
|
55
|
+
/** A map key's name: a node's from the host, else the key itself. */
|
|
56
|
+
declare function recordMapKeyLabel(decl: ValueDecl, key: string, adapter?: ValueAdapter): string;
|
|
57
|
+
/** A value as words, the way its control shows it: a pick's or a reference's name, flags joined, a boolean as
|
|
58
|
+
* the field's own name. Empty for a value that isn't set. */
|
|
59
|
+
declare function valueText(decl: ValueDecl, value: unknown, adapter?: ValueAdapter): string;
|
|
60
|
+
/** The inspector's summary of a map of records: a line per key, "TAM: smile, nod, WREN", the record's set
|
|
61
|
+
* fields in the manifest's order; a key with nothing set is its name alone. */
|
|
62
|
+
declare function recordMapSummary(decl: ValueDecl, value: unknown, adapter?: ValueAdapter): string[];
|
|
63
|
+
interface RecordMapGridOptions {
|
|
64
|
+
/** The map's declaration: `isRecordMap`. */
|
|
65
|
+
decl: ValueDecl;
|
|
66
|
+
/** The node's value, or undefined where it holds none. */
|
|
67
|
+
value: unknown;
|
|
68
|
+
/** The host's nodes, for a reference key and the cells' picks and references. */
|
|
69
|
+
adapter?: ValueAdapter;
|
|
70
|
+
/** Commit the whole map; undefined clears it. Absent: read-only. */
|
|
71
|
+
onCommit?: (value: unknown) => void;
|
|
72
|
+
disabled?: boolean;
|
|
73
|
+
/** The class on each cell's control, as the host's own rows carry. */
|
|
74
|
+
controlClassName?: string;
|
|
75
|
+
}
|
|
76
|
+
interface RecordMapGrid {
|
|
77
|
+
readonly el: HTMLElement;
|
|
78
|
+
update(opts: RecordMapGridOptions): void;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The grid: a row per key, a column per record field, each cell the row value-rows draws for that field (so
|
|
82
|
+
* picks, their checks and their problems are the same as in the inspector), a remove button per row, and the
|
|
83
|
+
* key adder under it. Keeps its cells across `update`, so a host that redraws on every change keeps the
|
|
84
|
+
* author's place.
|
|
85
|
+
*/
|
|
86
|
+
declare function recordMapGrid(initial: RecordMapGridOptions): RecordMapGrid;
|
|
87
|
+
|
|
53
88
|
/** A declaration of any type, as an extension's manifest writes it. */
|
|
54
89
|
interface ValueDecl extends FieldDeclLike {
|
|
55
90
|
/** The caption; the name when absent. */
|
|
@@ -135,4 +170,4 @@ interface ValueRows {
|
|
|
135
170
|
}
|
|
136
171
|
declare function valueRows(): ValueRows;
|
|
137
172
|
|
|
138
|
-
export { type ExtensionFold, type FoldSectionOptions, type ValueAdapter, type ValueDecl, type ValueNode, type ValueRowHandle, type ValueRowOptions, type ValueRows, extensionFold, foldCaption, isSet, valueRow, valueRows };
|
|
173
|
+
export { type ExtensionFold, type FoldSectionOptions, type RecordMapGrid, type RecordMapGridOptions, type ValueAdapter, type ValueDecl, type ValueNode, type ValueRowHandle, type ValueRowOptions, type ValueRows, extensionFold, foldCaption, isRecordMap, isSet, recordMapGrid, recordMapKeyLabel, recordMapSummary, valueRow, valueRows, valueText };
|
package/dist/value-rows.d.ts
CHANGED
|
@@ -50,6 +50,41 @@ declare function foldCaption(name: string, set: number): string;
|
|
|
50
50
|
*/
|
|
51
51
|
declare function extensionFold(): ExtensionFold;
|
|
52
52
|
|
|
53
|
+
/** A map whose values are records: edited in the grid, summarised in the inspector. */
|
|
54
|
+
declare function isRecordMap(decl: ValueDecl): boolean;
|
|
55
|
+
/** A map key's name: a node's from the host, else the key itself. */
|
|
56
|
+
declare function recordMapKeyLabel(decl: ValueDecl, key: string, adapter?: ValueAdapter): string;
|
|
57
|
+
/** A value as words, the way its control shows it: a pick's or a reference's name, flags joined, a boolean as
|
|
58
|
+
* the field's own name. Empty for a value that isn't set. */
|
|
59
|
+
declare function valueText(decl: ValueDecl, value: unknown, adapter?: ValueAdapter): string;
|
|
60
|
+
/** The inspector's summary of a map of records: a line per key, "TAM: smile, nod, WREN", the record's set
|
|
61
|
+
* fields in the manifest's order; a key with nothing set is its name alone. */
|
|
62
|
+
declare function recordMapSummary(decl: ValueDecl, value: unknown, adapter?: ValueAdapter): string[];
|
|
63
|
+
interface RecordMapGridOptions {
|
|
64
|
+
/** The map's declaration: `isRecordMap`. */
|
|
65
|
+
decl: ValueDecl;
|
|
66
|
+
/** The node's value, or undefined where it holds none. */
|
|
67
|
+
value: unknown;
|
|
68
|
+
/** The host's nodes, for a reference key and the cells' picks and references. */
|
|
69
|
+
adapter?: ValueAdapter;
|
|
70
|
+
/** Commit the whole map; undefined clears it. Absent: read-only. */
|
|
71
|
+
onCommit?: (value: unknown) => void;
|
|
72
|
+
disabled?: boolean;
|
|
73
|
+
/** The class on each cell's control, as the host's own rows carry. */
|
|
74
|
+
controlClassName?: string;
|
|
75
|
+
}
|
|
76
|
+
interface RecordMapGrid {
|
|
77
|
+
readonly el: HTMLElement;
|
|
78
|
+
update(opts: RecordMapGridOptions): void;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* The grid: a row per key, a column per record field, each cell the row value-rows draws for that field (so
|
|
82
|
+
* picks, their checks and their problems are the same as in the inspector), a remove button per row, and the
|
|
83
|
+
* key adder under it. Keeps its cells across `update`, so a host that redraws on every change keeps the
|
|
84
|
+
* author's place.
|
|
85
|
+
*/
|
|
86
|
+
declare function recordMapGrid(initial: RecordMapGridOptions): RecordMapGrid;
|
|
87
|
+
|
|
53
88
|
/** A declaration of any type, as an extension's manifest writes it. */
|
|
54
89
|
interface ValueDecl extends FieldDeclLike {
|
|
55
90
|
/** The caption; the name when absent. */
|
|
@@ -135,4 +170,4 @@ interface ValueRows {
|
|
|
135
170
|
}
|
|
136
171
|
declare function valueRows(): ValueRows;
|
|
137
172
|
|
|
138
|
-
export { type ExtensionFold, type FoldSectionOptions, type ValueAdapter, type ValueDecl, type ValueNode, type ValueRowHandle, type ValueRowOptions, type ValueRows, extensionFold, foldCaption, isSet, valueRow, valueRows };
|
|
173
|
+
export { type ExtensionFold, type FoldSectionOptions, type RecordMapGrid, type RecordMapGridOptions, type ValueAdapter, type ValueDecl, type ValueNode, type ValueRowHandle, type ValueRowOptions, type ValueRows, extensionFold, foldCaption, isRecordMap, isSet, recordMapGrid, recordMapKeyLabel, recordMapSummary, valueRow, valueRows, valueText };
|
package/dist/value-rows.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { fieldRow, fieldRowFocus } from './chunk-XJM733E6.js';
|
|
2
|
-
import { el,
|
|
2
|
+
import { el, iconBtn, iconNode, moveItem } from './chunk-W4WC4FO5.js';
|
|
3
3
|
import { stableStringify, defaultOf, pickChoices, valueProblems } from '@wildwinter/toolkit/extensions';
|
|
4
4
|
|
|
5
5
|
var isObject = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
@@ -78,13 +78,198 @@ function extensionFold() {
|
|
|
78
78
|
};
|
|
79
79
|
return fold;
|
|
80
80
|
}
|
|
81
|
+
var isObject2 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
82
|
+
function isRecordMap(decl) {
|
|
83
|
+
return decl.type === "map" && decl.of?.type === "record";
|
|
84
|
+
}
|
|
85
|
+
function recordMapKeyLabel(decl, key, adapter) {
|
|
86
|
+
const kind = decl.key?.type === "reference" ? decl.key.to ?? "" : void 0;
|
|
87
|
+
if (kind === void 0 || !adapter) return key;
|
|
88
|
+
return adapter.nodes(kind).find((n) => n.id === key)?.label ?? adapter.label?.(kind, key) ?? key;
|
|
89
|
+
}
|
|
90
|
+
function valueText(decl, value, adapter) {
|
|
91
|
+
if (!isSet(decl, value)) return "";
|
|
92
|
+
if (decl.type === "pick" && typeof value === "string") {
|
|
93
|
+
const choice = pickChoices(decl, {
|
|
94
|
+
...adapter ? { nodes: (kind) => adapter.nodes(kind) } : {},
|
|
95
|
+
...adapter?.list ? { list: (name) => adapter.list(name) } : {}
|
|
96
|
+
}).find((c) => c.value === value);
|
|
97
|
+
return choice?.label ?? value;
|
|
98
|
+
}
|
|
99
|
+
if (decl.type === "reference" && typeof value === "string" && decl.to !== void 0 && adapter) {
|
|
100
|
+
return adapter.nodes(decl.to).find((n) => n.id === value)?.label ?? adapter.label?.(decl.to, value) ?? value;
|
|
101
|
+
}
|
|
102
|
+
if (decl.type === "boolean") return value === true ? decl.label ?? decl.name : "";
|
|
103
|
+
if (Array.isArray(value)) return value.map(String).join(", ");
|
|
104
|
+
if (isObject2(value)) return JSON.stringify(value);
|
|
105
|
+
return String(value);
|
|
106
|
+
}
|
|
107
|
+
function recordMapSummary(decl, value, adapter) {
|
|
108
|
+
if (!isObject2(value)) return [];
|
|
109
|
+
const fields = decl.of?.fields ?? [];
|
|
110
|
+
return Object.entries(value).map(([key, record]) => {
|
|
111
|
+
const name = recordMapKeyLabel(decl, key, adapter);
|
|
112
|
+
const words = isObject2(record) ? fields.map((f) => valueText(f, record[f.name], adapter)).filter((w) => w !== "") : [];
|
|
113
|
+
return words.length > 0 ? `${name}: ${words.join(", ")}` : name;
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
function recordMapGrid(initial) {
|
|
117
|
+
let opts = initial;
|
|
118
|
+
const root = el("div", "shell-recordgrid");
|
|
119
|
+
const table = el("table", "shell-recordgrid-table");
|
|
120
|
+
const head = el("thead");
|
|
121
|
+
const body = el("tbody");
|
|
122
|
+
table.append(head, body);
|
|
123
|
+
const adder = el("div", "shell-recordgrid-add");
|
|
124
|
+
const empty = el("p", "shell-recordgrid-empty");
|
|
125
|
+
root.append(table, empty, adder);
|
|
126
|
+
const cells = /* @__PURE__ */ new Map();
|
|
127
|
+
let addKey = "";
|
|
128
|
+
const editable = () => opts.onCommit !== void 0 && opts.disabled !== true;
|
|
129
|
+
const held = () => isObject2(opts.value) ? opts.value : {};
|
|
130
|
+
const commit = (next) => {
|
|
131
|
+
const v = Object.keys(next).length > 0 ? next : void 0;
|
|
132
|
+
opts = { ...opts, value: v };
|
|
133
|
+
draw();
|
|
134
|
+
opts.onCommit?.(v);
|
|
135
|
+
};
|
|
136
|
+
const cell = (key, field, record) => {
|
|
137
|
+
const id = `${key}\0${field.name}`;
|
|
138
|
+
const o = {
|
|
139
|
+
decl: field,
|
|
140
|
+
value: record[field.name],
|
|
141
|
+
...opts.adapter ? { adapter: opts.adapter } : {},
|
|
142
|
+
...opts.disabled !== void 0 ? { disabled: opts.disabled } : {},
|
|
143
|
+
...opts.controlClassName !== void 0 ? { controlClassName: opts.controlClassName } : {},
|
|
144
|
+
...editable() ? {
|
|
145
|
+
onCommit: (v) => {
|
|
146
|
+
const map = held();
|
|
147
|
+
const rec = { ...isObject2(map[key]) ? map[key] : {} };
|
|
148
|
+
if (v === void 0) delete rec[field.name];
|
|
149
|
+
else rec[field.name] = v;
|
|
150
|
+
commit({ ...map, [key]: rec });
|
|
151
|
+
}
|
|
152
|
+
} : {},
|
|
153
|
+
className: "shell-recordgrid-cell"
|
|
154
|
+
};
|
|
155
|
+
const had = cells.get(id);
|
|
156
|
+
if (had && had.el.dataset["type"] === field.type) {
|
|
157
|
+
fieldRowFocus.settle(had.el);
|
|
158
|
+
had.update(o);
|
|
159
|
+
fieldRowFocus.restore(had.el);
|
|
160
|
+
return had.el;
|
|
161
|
+
}
|
|
162
|
+
const handle = valueRow(o);
|
|
163
|
+
handle.el.dataset["type"] = field.type;
|
|
164
|
+
cells.set(id, handle);
|
|
165
|
+
return handle.el;
|
|
166
|
+
};
|
|
167
|
+
const draw = () => {
|
|
168
|
+
const decl = opts.decl;
|
|
169
|
+
const fields = decl.of?.fields ?? [];
|
|
170
|
+
const map = held();
|
|
171
|
+
const keys = Object.keys(map);
|
|
172
|
+
const adapter = opts.adapter;
|
|
173
|
+
const keyKind = decl.key?.type === "reference" ? decl.key.to ?? "" : void 0;
|
|
174
|
+
const keyNodes = keyKind !== void 0 && adapter ? adapter.nodes(keyKind) : void 0;
|
|
175
|
+
const hr = el("tr");
|
|
176
|
+
hr.append(el("th", "shell-recordgrid-keyhead", recordMapKeyHeading(decl)));
|
|
177
|
+
for (const f of fields) {
|
|
178
|
+
const th = el("th", void 0, f.label ?? f.name);
|
|
179
|
+
const help = f.help ?? f.purpose;
|
|
180
|
+
if (help) th.dataset["tip"] = help;
|
|
181
|
+
hr.append(th);
|
|
182
|
+
}
|
|
183
|
+
hr.append(el("th", "shell-recordgrid-tools"));
|
|
184
|
+
head.replaceChildren(hr);
|
|
185
|
+
const used = /* @__PURE__ */ new Set();
|
|
186
|
+
const rows = [];
|
|
187
|
+
for (const key of keys) {
|
|
188
|
+
const record = isObject2(map[key]) ? map[key] : {};
|
|
189
|
+
const tr = el("tr");
|
|
190
|
+
tr.dataset["key"] = key;
|
|
191
|
+
const name = recordMapKeyLabel(decl, key, adapter);
|
|
192
|
+
const keyCell = el("th", "shell-recordgrid-key", name);
|
|
193
|
+
keyCell.setAttribute("scope", "row");
|
|
194
|
+
if (keyNodes !== void 0 && adapter && keyNodes.every((n) => n.id !== key) && adapter.label?.(keyKind, key) === void 0) {
|
|
195
|
+
keyCell.append(el("span", "shell-recordgrid-gone", " (not here any more)"));
|
|
196
|
+
}
|
|
197
|
+
tr.append(keyCell);
|
|
198
|
+
for (const f of fields) {
|
|
199
|
+
used.add(`${key}\0${f.name}`);
|
|
200
|
+
const td = el("td");
|
|
201
|
+
td.append(cell(key, f, record));
|
|
202
|
+
tr.append(td);
|
|
203
|
+
}
|
|
204
|
+
const tools = el("td", "shell-recordgrid-tools");
|
|
205
|
+
if (editable()) tools.append(iconBtn("close", `Remove ${name}`, () => {
|
|
206
|
+
const next = { ...held() };
|
|
207
|
+
delete next[key];
|
|
208
|
+
commit(next);
|
|
209
|
+
}));
|
|
210
|
+
tr.append(tools);
|
|
211
|
+
rows.push(tr);
|
|
212
|
+
}
|
|
213
|
+
for (const id of [...cells.keys()]) if (!used.has(id)) cells.delete(id);
|
|
214
|
+
body.replaceChildren(...rows);
|
|
215
|
+
table.hidden = keys.length === 0;
|
|
216
|
+
empty.textContent = keys.length === 0 ? "None yet." : "";
|
|
217
|
+
empty.hidden = keys.length !== 0;
|
|
218
|
+
adder.replaceChildren();
|
|
219
|
+
if (!editable()) return;
|
|
220
|
+
const add = (k) => {
|
|
221
|
+
if (k === "" || Object.prototype.hasOwnProperty.call(held(), k)) return;
|
|
222
|
+
commit({ ...held(), [k]: defaultOf(decl.of) });
|
|
223
|
+
};
|
|
224
|
+
if (keyNodes !== void 0) {
|
|
225
|
+
const pick = el("select", `field shell-valuerow-key${opts.controlClassName ? ` ${opts.controlClassName}` : ""}`);
|
|
226
|
+
const first = el("option", void 0, "Add...");
|
|
227
|
+
first.value = "";
|
|
228
|
+
pick.append(first);
|
|
229
|
+
for (const n of keyNodes.filter((n2) => !Object.prototype.hasOwnProperty.call(map, n2.id))) {
|
|
230
|
+
const opt = el("option", void 0, n.label);
|
|
231
|
+
opt.value = n.id;
|
|
232
|
+
pick.append(opt);
|
|
233
|
+
}
|
|
234
|
+
pick.disabled = pick.options.length === 1;
|
|
235
|
+
pick.addEventListener("change", () => add(pick.value));
|
|
236
|
+
adder.append(pick);
|
|
237
|
+
} else {
|
|
238
|
+
const input = el("input", "field shell-valuerow-key");
|
|
239
|
+
input.type = "text";
|
|
240
|
+
input.placeholder = "New key";
|
|
241
|
+
input.value = addKey;
|
|
242
|
+
input.addEventListener("input", () => {
|
|
243
|
+
addKey = input.value;
|
|
244
|
+
});
|
|
245
|
+
const go = () => {
|
|
246
|
+
const k = input.value.trim();
|
|
247
|
+
addKey = "";
|
|
248
|
+
add(k);
|
|
249
|
+
};
|
|
250
|
+
input.addEventListener("keydown", (e) => {
|
|
251
|
+
if (e.key === "Enter") go();
|
|
252
|
+
});
|
|
253
|
+
adder.append(input, iconBtn("add", "Add", go));
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
draw();
|
|
257
|
+
return { el: root, update: (o) => {
|
|
258
|
+
opts = o;
|
|
259
|
+
draw();
|
|
260
|
+
} };
|
|
261
|
+
}
|
|
262
|
+
function recordMapKeyHeading(decl) {
|
|
263
|
+
const to = decl.key?.type === "reference" ? decl.key.to : void 0;
|
|
264
|
+
return to ? to.charAt(0).toUpperCase() + to.slice(1) : "Key";
|
|
265
|
+
}
|
|
81
266
|
|
|
82
267
|
// src/value-rows.ts
|
|
83
268
|
function nodeLabel(adapter, kind, id) {
|
|
84
269
|
return adapter.nodes(kind).find((n) => n.id === id)?.label ?? adapter.label?.(kind, id);
|
|
85
270
|
}
|
|
86
271
|
var SCALARS = /* @__PURE__ */ new Set(["text", "multiline", "number", "boolean", "enum", "flags", "quality", "string"]);
|
|
87
|
-
var
|
|
272
|
+
var isObject3 = (v) => typeof v === "object" && v !== null && !Array.isArray(v);
|
|
88
273
|
var nameOf = (decl) => decl.label ?? decl.name;
|
|
89
274
|
var asDecl = (d, name) => ({ ...d, name: d.name ?? name });
|
|
90
275
|
function ownProblems(decl, value, adapter) {
|
|
@@ -323,31 +508,31 @@ function structuredRow(initial) {
|
|
|
323
508
|
}, controls));
|
|
324
509
|
};
|
|
325
510
|
if (decl.type === "record") {
|
|
326
|
-
const value =
|
|
511
|
+
const value = isObject3(o.value) ? o.value : void 0;
|
|
327
512
|
const required = value === void 0 ? [] : valueProblems(decl, value).filter((p) => p.code === "required");
|
|
328
513
|
for (const f of decl.fields ?? []) {
|
|
329
514
|
const missing = required.find((p) => p.path === f.name);
|
|
330
515
|
child(`f:${f.name}`, f, value?.[f.name], (v) => {
|
|
331
|
-
const next = { ...
|
|
516
|
+
const next = { ...isObject3(opts.value) ? opts.value : {} };
|
|
332
517
|
if (v === void 0) delete next[f.name];
|
|
333
518
|
else next[f.name] = v;
|
|
334
519
|
commit(Object.keys(next).length > 0 ? next : void 0);
|
|
335
520
|
}, void 0, void 0, missing ? "Required." : void 0);
|
|
336
521
|
}
|
|
337
522
|
} else if (decl.type === "map" && decl.of) {
|
|
338
|
-
const value =
|
|
523
|
+
const value = isObject3(o.value) ? o.value : {};
|
|
339
524
|
const keyNodes = decl.key?.type === "reference" && o.adapter ? o.adapter.nodes(decl.key.to ?? "") : void 0;
|
|
340
525
|
const keyKind = decl.key?.to ?? "";
|
|
341
526
|
const keyLabel = (k) => (o.adapter && keyNodes !== void 0 ? nodeLabel(o.adapter, keyKind, k) : void 0) ?? k;
|
|
342
527
|
for (const k of Object.keys(value)) {
|
|
343
528
|
const remove = editable() ? [iconBtn("close", `Remove ${keyLabel(k)}`, () => {
|
|
344
|
-
const next = { ...
|
|
529
|
+
const next = { ...isObject3(opts.value) ? opts.value : {} };
|
|
345
530
|
delete next[k];
|
|
346
531
|
commit(Object.keys(next).length > 0 ? next : void 0);
|
|
347
532
|
})] : [];
|
|
348
533
|
const gone = keyNodes !== void 0 && o.adapter && nodeLabel(o.adapter, keyKind, k) === void 0 ? `${k} is not here any more.` : void 0;
|
|
349
534
|
child(`k:${k}`, asDecl(decl.of, k), value[k], (v) => {
|
|
350
|
-
const next = { ...
|
|
535
|
+
const next = { ...isObject3(opts.value) ? opts.value : {} };
|
|
351
536
|
next[k] = v === void 0 ? defaultOf(decl.of) : v;
|
|
352
537
|
commit(next);
|
|
353
538
|
}, remove, keyLabel(k), gone);
|
|
@@ -391,7 +576,7 @@ function structuredRow(initial) {
|
|
|
391
576
|
}
|
|
392
577
|
} else if (decl.type === "list" && decl.of) {
|
|
393
578
|
const value = Array.isArray(o.value) ? o.value : [];
|
|
394
|
-
const idOf = (item, i) => decl.id !== void 0 &&
|
|
579
|
+
const idOf = (item, i) => decl.id !== void 0 && isObject3(item) && typeof item[decl.id] === "string" ? `id:${item[decl.id]}` : `i:${i}`;
|
|
395
580
|
value.forEach((item, i) => {
|
|
396
581
|
const set = (next) => commit(next.length > 0 ? next : void 0);
|
|
397
582
|
const controls = editable() ? [
|
|
@@ -405,7 +590,7 @@ function structuredRow(initial) {
|
|
|
405
590
|
}, i === value.length - 1),
|
|
406
591
|
iconBtn("close", "Remove", () => set(value.filter((_, j) => j !== i)), false, true)
|
|
407
592
|
] : [];
|
|
408
|
-
const itemLabel = decl.id !== void 0 &&
|
|
593
|
+
const itemLabel = decl.id !== void 0 && isObject3(item) && typeof item[decl.id] === "string" ? item[decl.id] : `${i + 1}`;
|
|
409
594
|
child(idOf(item, i), asDecl(decl.of, itemLabel), item, (v) => {
|
|
410
595
|
const next = [...Array.isArray(opts.value) ? opts.value : []];
|
|
411
596
|
next[i] = v === void 0 ? defaultOf(decl.of) : v;
|
|
@@ -416,8 +601,8 @@ function structuredRow(initial) {
|
|
|
416
601
|
if (editable()) {
|
|
417
602
|
adder.append(iconBtn("add", "Add", () => {
|
|
418
603
|
const fresh = defaultOf(decl.of);
|
|
419
|
-
if (decl.id !== void 0 &&
|
|
420
|
-
const taken = new Set(value.map((x) =>
|
|
604
|
+
if (decl.id !== void 0 && isObject3(fresh)) {
|
|
605
|
+
const taken = new Set(value.map((x) => isObject3(x) ? x[decl.id] : void 0));
|
|
421
606
|
let n = value.length + 1;
|
|
422
607
|
while (taken.has(`item-${n}`)) n++;
|
|
423
608
|
fresh[decl.id] = `item-${n}`;
|
|
@@ -466,6 +651,6 @@ function valueRows() {
|
|
|
466
651
|
};
|
|
467
652
|
}
|
|
468
653
|
|
|
469
|
-
export { extensionFold, foldCaption, isSet, valueRow, valueRows };
|
|
654
|
+
export { extensionFold, foldCaption, isRecordMap, isSet, recordMapGrid, recordMapKeyLabel, recordMapSummary, valueRow, valueRows, valueText };
|
|
470
655
|
//# sourceMappingURL=value-rows.js.map
|
|
471
656
|
//# sourceMappingURL=value-rows.js.map
|