@fuaran-ui/ops 0.6.0 → 0.7.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/dist/index.js CHANGED
@@ -428,7 +428,10 @@ var binding = (b, staticEnc = objValue) => {
428
428
  return caseObj("Transform", [
429
429
  ...paramFields,
430
430
  ["pipeline", jArray(b.pipeline.map(transformStep))],
431
- ["source", dataSource(b.source)]
431
+ [
432
+ "source",
433
+ b.source.kind === "Data" ? dataSource(b.source.source) : binding(b.source.binding, jsonValue)
434
+ ]
432
435
  ]);
433
436
  }
434
437
  case "Invoke":
@@ -462,11 +465,12 @@ var action = (a) => {
462
465
  ]);
463
466
  case "Navigate":
464
467
  return caseObj("Navigate", [["route", str(a.route)]]);
465
- case "SetState":
466
- return caseObj("SetState", [
467
- ["key", str(a.key)],
468
- ["value", jsonValue(a.value)]
469
- ]);
468
+ case "SetState": {
469
+ const fields = [["key", str(a.key)]];
470
+ if (a.value !== void 0) fields.push(["value", jsonValue(a.value)]);
471
+ if (a.valueFrom !== void 0) fields.push(["valueFrom", binding(a.valueFrom, jsonValue)]);
472
+ return caseObj("SetState", fields);
473
+ }
470
474
  case "AiTool":
471
475
  return caseObj("AiTool", [
472
476
  ["args", jsonValue(a.args)],
@@ -522,6 +526,13 @@ var cellFormat = (f) => {
522
526
  return caseObj("SignificantDigits", [["digits", num(f.digits)]]);
523
527
  case "Date":
524
528
  return caseObj("Date", [["format", str(f.format)]]);
529
+ case "Duration":
530
+ return caseObj("Duration", [
531
+ ["style", str(f.style)],
532
+ ["unit", str(f.unit)]
533
+ ]);
534
+ case "RelativeTime":
535
+ return caseObj("RelativeTime", [["unit", str(f.unit)]]);
525
536
  case "Custom":
526
537
  return caseObj("Custom", [["fn", CLOSURE]]);
527
538
  default:
@@ -540,6 +551,11 @@ var formatIntent = (f) => {
540
551
  return caseObj("Date", [["dateStyle", str(f.dateStyle)]]);
541
552
  case "RelativeTime":
542
553
  return caseObj("RelativeTime", [["unit", str(f.unit)]]);
554
+ case "Duration":
555
+ return caseObj("Duration", [
556
+ ["style", str(f.style)],
557
+ ["unit", str(f.unit)]
558
+ ]);
543
559
  default:
544
560
  return assertNever(f);
545
561
  }
@@ -635,6 +651,7 @@ var linkSpec = (s) => {
635
651
  ];
636
652
  if (s.rel !== void 0) fields.push(["rel", str(s.rel)]);
637
653
  if (s.target !== void 0) fields.push(["target", str(s.target)]);
654
+ if (s.protection !== void 0) fields.push(["protection", str(s.protection)]);
638
655
  return jObject(fields);
639
656
  };
640
657
  var imageSpec = (s) => jObject([
@@ -672,6 +689,13 @@ var mathSpec = (s) => jObject([
672
689
  ]);
673
690
  var sparklineSpec = (s) => jObject([["source", binding(s.source, staticFloatSeq)]]);
674
691
  var skeletonSpec = (s) => jObject([["rows", num(s.rows)]]);
692
+ var iconSpec = (s) => {
693
+ const fields = [["icon", str(s.icon)]];
694
+ if (s.label !== void 0) fields.push(["label", str(s.label)]);
695
+ if (s.size !== "Medium") fields.push(["size", str(s.size)]);
696
+ pushToneOptional(fields, s.tone);
697
+ return jObject(fields);
698
+ };
675
699
  var calloutSpec = (s) => {
676
700
  const fields = [
677
701
  ["body", textSource(s.body)],
@@ -715,6 +739,8 @@ var drawStyle = (s) => {
715
739
  if (s.emphasis !== void 0) fields.push(["emphasis", str(s.emphasis)]);
716
740
  if (s.fontFamily !== void 0) fields.push(["fontFamily", str(s.fontFamily)]);
717
741
  if (s.markId !== void 0) fields.push(["markId", str(s.markId)]);
742
+ if (s.rotation !== void 0) fields.push(["rotation", num(s.rotation)]);
743
+ if (s.tip !== void 0) fields.push(["tip", textSource(s.tip)]);
718
744
  return jObject(fields);
719
745
  };
720
746
  var curveCommand = (c) => {
@@ -831,6 +857,8 @@ var displayKind = (d) => {
831
857
  return hoistSpec("Progress", progressSpec(d.spec));
832
858
  case "Skeleton":
833
859
  return hoistSpec("Skeleton", skeletonSpec(d.spec));
860
+ case "Icon":
861
+ return hoistSpec("Icon", iconSpec(d.spec));
834
862
  case "LabelValueRow":
835
863
  return hoistSpec("LabelValueRow", labelValueRowSpec(d.spec));
836
864
  case "Fact":
@@ -1138,8 +1166,14 @@ var columnErased = (c) => {
1138
1166
  pushColumnWidthOptional(fields, "width", c.width);
1139
1167
  if (c.value !== void 0) fields.push(["value", CLOSURE]);
1140
1168
  if (c.field !== void 0) fields.push(["field", str(c.field)]);
1169
+ if (c.sortable !== void 0) fields.push(["sortable", bool(c.sortable)]);
1170
+ if (c.editable !== void 0) fields.push(["editable", bool(c.editable)]);
1141
1171
  return jObject(fields);
1142
1172
  };
1173
+ var defaultSortJson = (d) => jObject([
1174
+ ["column", intLit(d.column)],
1175
+ ["direction", str(d.direction)]
1176
+ ]);
1143
1177
  var gridSpec = (s) => {
1144
1178
  const fields = [
1145
1179
  ["columns", jArray(s.columns.map(columnErased))],
@@ -1151,14 +1185,22 @@ var gridSpec = (s) => {
1151
1185
  if (s.onRowClick !== void 0) fields.push(["onRowClick", CLOSURE]);
1152
1186
  if (s.rowKey !== void 0) fields.push(["rowKey", CLOSURE]);
1153
1187
  if (s.rowKeyField !== void 0) fields.push(["rowKeyField", str(s.rowKeyField)]);
1154
- if (s.staticRows !== void 0)
1155
- fields.push([
1156
- "staticRows",
1157
- jObject([
1158
- ["headers", jArray(s.staticRows.headers.map(textSource))],
1159
- ["rows", jArray(s.staticRows.rows.map((row) => jArray(row.map(textSource))))]
1160
- ])
1161
- ]);
1188
+ if (s.sortStateKey !== void 0) fields.push(["sortStateKey", str(s.sortStateKey)]);
1189
+ if (s.pageSize !== void 0) fields.push(["pageSize", num(s.pageSize)]);
1190
+ if (s.pageStateKey !== void 0) fields.push(["pageStateKey", str(s.pageStateKey)]);
1191
+ if (s.defaultSort !== void 0) fields.push(["defaultSort", defaultSortJson(s.defaultSort)]);
1192
+ if (s.editStateKey !== void 0) fields.push(["editStateKey", str(s.editStateKey)]);
1193
+ if (s.staticRows !== void 0) {
1194
+ const sr = s.staticRows;
1195
+ const srFields = [
1196
+ ["headers", jArray(sr.headers.map(textSource))],
1197
+ ["rows", jArray(sr.rows.map((row) => jArray(row.map(textSource))))]
1198
+ ];
1199
+ if (sr.sortable !== void 0) srFields.push(["sortable", bool(sr.sortable)]);
1200
+ if (sr.defaultSort !== void 0)
1201
+ srFields.push(["defaultSort", defaultSortJson(sr.defaultSort)]);
1202
+ fields.push(["staticRows", jObject(srFields)]);
1203
+ }
1162
1204
  return jObject(fields);
1163
1205
  };
1164
1206
  var chartSpec = (s) => {
@@ -1171,6 +1213,13 @@ var chartSpec = (s) => {
1171
1213
  ["yFields", jArray(s.yFields.map(str))]
1172
1214
  ];
1173
1215
  if (s.title !== void 0) fields.push(["title", textSource(s.title)]);
1216
+ if (s.valueFormat !== void 0) fields.push(["valueFormat", formatIntent(s.valueFormat)]);
1217
+ if (s.xTitle !== void 0) fields.push(["xTitle", textSource(s.xTitle)]);
1218
+ if (s.yTitle !== void 0) fields.push(["yTitle", textSource(s.yTitle)]);
1219
+ if (s.subtitle !== void 0) fields.push(["subtitle", textSource(s.subtitle)]);
1220
+ if (s.legendPosition !== void 0) fields.push(["legendPosition", str(s.legendPosition)]);
1221
+ if (s.dataLabels !== void 0) fields.push(["dataLabels", str(s.dataLabels)]);
1222
+ if (s.xScale !== void 0) fields.push(["xScale", str(s.xScale)]);
1174
1223
  if (s.onPointClick !== void 0) fields.push(["onPointClick", CLOSURE]);
1175
1224
  return jObject(fields);
1176
1225
  };
@@ -3089,12 +3138,23 @@ var decodeTextAnchor = (p, j) => bareEnum(p, j, ["Start", "Middle", "End"], "Tex
3089
3138
  var decodeStyleRole = (p, j) => bareEnum(p, j, ["None", "Eyebrow", "Data", "Lede", "Caption"], "StyleRole");
3090
3139
  var decodeFontVoice = (p, j) => bareEnum(p, j, ["Default", "Display", "Structural"], "FontVoice");
3091
3140
  var decodeChartKind = (p, j) => bareEnum(p, j, ["Line", "Bar", "Area", "Pie", "Scatter", "Heatmap"], "ChartKind");
3141
+ var decodeChartLegendPosition = (p, j) => bareEnum(p, j, ["Top", "Right", "Bottom", "None"], "ChartLegendPosition");
3142
+ var decodeChartDataLabels = (p, j) => bareEnum(p, j, ["Off", "Ends"], "ChartDataLabels");
3143
+ var decodeChartXScale = (p, j) => bareEnum(p, j, ["Category", "Temporal"], "ChartXScale");
3092
3144
  var decodeFileReadEncoding = (p, j) => bareEnum(p, j, ["Text", "Base64", "DataUrl"], "FileReadEncoding");
3093
3145
  var decodeAriaRole = (p, j) => {
3094
3146
  if (j.kind !== "JString") return wrongType(p, "JSON string (ARIA role)");
3095
3147
  return ok(j.value);
3096
3148
  };
3097
3149
  var decodeLiveRegion = (p, j) => bareEnum(p, j, ["polite", "assertive", "off"], "LiveRegionKind");
3150
+ var decodeDurationUnit = (p, j) => bareEnum(p, j, ["Seconds", "Minutes", "Hours"], "DurationUnit");
3151
+ var decodeDurationStyle = (p, j) => bareEnum(p, j, ["Compact", "Clock", "Long"], "DurationStyle");
3152
+ var decodeRelativeTimeUnit = (p, j) => bareEnum(
3153
+ p,
3154
+ j,
3155
+ ["Second", "Minute", "Hour", "Day", "Week", "Month", "Year"],
3156
+ "RelativeTimeUnit"
3157
+ );
3098
3158
  var decodeCellFormat = (path, j) => {
3099
3159
  const fo = requireObject(path, j);
3100
3160
  if (!fo.ok) return fo;
@@ -3129,13 +3189,24 @@ var decodeCellFormat = (path, j) => {
3129
3189
  const r = reqField(path, f, "format", "format string", requireString);
3130
3190
  return r.ok ? ok({ kind: "Date", format: r.value }) : r;
3131
3191
  }
3192
+ case "Duration": {
3193
+ const unit = reqField(path, f, "unit", "DurationUnit string", decodeDurationUnit);
3194
+ if (!unit.ok) return unit;
3195
+ const style = reqField(path, f, "style", "DurationStyle string", decodeDurationStyle);
3196
+ if (!style.ok) return style;
3197
+ return ok({ kind: "Duration", unit: unit.value, style: style.value });
3198
+ }
3199
+ case "RelativeTime": {
3200
+ const r = reqField(path, f, "unit", "RelativeTimeUnit string", decodeRelativeTimeUnit);
3201
+ return r.ok ? ok({ kind: "RelativeTime", unit: r.value }) : r;
3202
+ }
3132
3203
  case "Custom":
3133
3204
  return ok({ kind: "Custom", format: () => CLOSURE2 });
3134
3205
  default:
3135
3206
  return unknownDuCase(
3136
3207
  path,
3137
3208
  d.value,
3138
- "None | Number | Currency | Percent | SignificantDigits | Date | Custom"
3209
+ "None | Number | Currency | Percent | SignificantDigits | Date | Duration | RelativeTime | Custom"
3139
3210
  );
3140
3211
  }
3141
3212
  };
@@ -3173,22 +3244,22 @@ var decodeFormat = (path, j) => {
3173
3244
  return r.ok ? ok({ kind: "Date", dateStyle: r.value }) : r;
3174
3245
  }
3175
3246
  case "RelativeTime": {
3176
- const r = reqField(
3177
- path,
3178
- f,
3179
- "unit",
3180
- "RelativeTimeUnit string",
3181
- (p, v) => bareEnum(
3182
- p,
3183
- v,
3184
- ["Second", "Minute", "Hour", "Day", "Week", "Month", "Year"],
3185
- "RelativeTimeUnit"
3186
- )
3187
- );
3247
+ const r = reqField(path, f, "unit", "RelativeTimeUnit string", decodeRelativeTimeUnit);
3188
3248
  return r.ok ? ok({ kind: "RelativeTime", unit: r.value }) : r;
3189
3249
  }
3250
+ case "Duration": {
3251
+ const unit = reqField(path, f, "unit", "DurationUnit string", decodeDurationUnit);
3252
+ if (!unit.ok) return unit;
3253
+ const style = reqField(path, f, "style", "DurationStyle string", decodeDurationStyle);
3254
+ if (!style.ok) return style;
3255
+ return ok({ kind: "Duration", unit: unit.value, style: style.value });
3256
+ }
3190
3257
  default:
3191
- return unknownDuCase(path, d.value, "Number | Currency | Percent | Date | RelativeTime");
3258
+ return unknownDuCase(
3259
+ path,
3260
+ d.value,
3261
+ "Number | Currency | Percent | Date | RelativeTime | Duration"
3262
+ );
3192
3263
  }
3193
3264
  };
3194
3265
  var decodeLocaleSource = (path, j) => {
@@ -4242,8 +4313,35 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
4242
4313
  if (!srcJ.ok) return srcJ;
4243
4314
  const pipeJ = requireField(path, f, "pipeline", "Transform pipeline array");
4244
4315
  if (!pipeJ.ok) return pipeJ;
4245
- const src = decodeDataSource(srcJ.value);
4246
- if (!src.ok) return makeError("WRONG_TYPE", `${path}.source`, src.error);
4316
+ const liveTagAst = srcJ.value.kind === "JObject" ? srcJ.value.fields.get("$type") : void 0;
4317
+ const liveTag = liveTagAst !== void 0 && liveTagAst.kind === "JString" && (liveTagAst.value === "State" || liveTagAst.value === "Selection" || liveTagAst.value === "Query") ? liveTagAst.value : void 0;
4318
+ const hasCarried = srcJ.value.kind === "JObject" && srcJ.value.fields.has("defaultValue");
4319
+ let source;
4320
+ if (liveTag === void 0 || liveTag === "State" && !hasCarried) {
4321
+ const src = decodeDataSource(normaliseTransformSource(srcJ.value));
4322
+ if (!src.ok) return makeError("WRONG_TYPE", `${path}.source`, src.error);
4323
+ source = { kind: "Data", source: src.value };
4324
+ } else {
4325
+ const b2 = decodeBinding(`${path}.source`, srcJ.value, decodeJVal, void 0);
4326
+ if (!b2.ok) return b2;
4327
+ if (liveTag === "State") {
4328
+ const snap = decodeDataSource(normaliseTransformSource(srcJ.value));
4329
+ if (!snap.ok) return makeError("WRONG_TYPE", `${path}.source`, snap.error);
4330
+ source = {
4331
+ kind: "Live",
4332
+ binding: b2.value,
4333
+ initial: snap.value
4334
+ };
4335
+ } else {
4336
+ const dv = srcJ.value.kind === "JObject" ? srcJ.value.fields.get("defaultValue") : void 0;
4337
+ const snap = dv !== void 0 ? decodeDataSource(normaliseTransformSource(dv)) : void 0;
4338
+ source = {
4339
+ kind: "Live",
4340
+ binding: b2.value,
4341
+ initial: snap !== void 0 && snap.ok ? snap.value : { kind: "Embedded", table: { schema: [], columns: [] } }
4342
+ };
4343
+ }
4344
+ }
4247
4345
  const pipe = decodePipelineCore(pipeJ.value);
4248
4346
  if (!pipe.ok) return makeError("WRONG_TYPE", `${path}.pipeline`, pipe.error);
4249
4347
  const paramsField = tryField(f, "params");
@@ -4294,7 +4392,7 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
4294
4392
  }
4295
4393
  const b = {
4296
4394
  kind: "Transform",
4297
- source: src.value,
4395
+ source,
4298
4396
  pipeline: pipe.value,
4299
4397
  ...params !== void 0 ? { params } : {}
4300
4398
  };
@@ -4329,6 +4427,62 @@ var decodeBinding = (path, j, parseStatic = (_p, v) => ok(decodeAstValue(v)), pl
4329
4427
  );
4330
4428
  }
4331
4429
  };
4430
+ var normaliseTransformSource = (j) => {
4431
+ let unwrapped = j;
4432
+ if (j.kind === "JObject") {
4433
+ const t = j.fields.get("$type");
4434
+ if (t !== void 0 && t.kind === "JString" && (t.value === "State" || t.value === "Static" || t.value === "Bound")) {
4435
+ const inner = j.fields.get("defaultValue") ?? j.fields.get("value");
4436
+ if (inner !== void 0) unwrapped = inner;
4437
+ }
4438
+ }
4439
+ if (unwrapped.kind === "JArray" && unwrapped.items.length > 0 && unwrapped.items[0].kind === "JObject") {
4440
+ const rows = unwrapped.items;
4441
+ const first = unwrapped.items[0];
4442
+ const keys = [...first.fields.keys()].sort((a, b) => a < b ? -1 : a > b ? 1 : 0);
4443
+ const cols = /* @__PURE__ */ new Map();
4444
+ for (const k of keys) {
4445
+ const cells = rows.map((row) => {
4446
+ if (row.kind !== "JObject") return { kind: "JNull" };
4447
+ return row.fields.get(k) ?? { kind: "JNull" };
4448
+ });
4449
+ cols.set(k, { kind: "JArray", items: cells });
4450
+ }
4451
+ return {
4452
+ kind: "JObject",
4453
+ fields: /* @__PURE__ */ new Map([["columns", { kind: "JObject", fields: cols }]])
4454
+ };
4455
+ }
4456
+ return unwrapped;
4457
+ };
4458
+ var liveValueToTable = (v) => {
4459
+ if (v === void 0) return { ok: false, error: "Transform live source resolved to no value" };
4460
+ let text;
4461
+ try {
4462
+ text = JSON.stringify(v);
4463
+ } catch {
4464
+ return {
4465
+ ok: false,
4466
+ error: "Transform live source resolved to a value with no JSON representation"
4467
+ };
4468
+ }
4469
+ if (text === void 0) {
4470
+ return { ok: false, error: "Transform live source resolved to no value" };
4471
+ }
4472
+ const parsed = parse(text);
4473
+ if (!parsed.ok) {
4474
+ return { ok: false, error: "Transform live source resolved to unreadable data" };
4475
+ }
4476
+ const src = decodeDataSource(normaliseTransformSource(parsed.value));
4477
+ if (!src.ok) return { ok: false, error: src.error };
4478
+ if (src.value.kind !== "Embedded") {
4479
+ return {
4480
+ ok: false,
4481
+ error: `Transform live source resolved to a 'ref' source ('${src.value.name}'), which is not host-resolved`
4482
+ };
4483
+ }
4484
+ return { ok: true, value: src.value.table };
4485
+ };
4332
4486
  var decodeBindingArgs = (path, j) => {
4333
4487
  const fo = requireObject(path, j);
4334
4488
  if (!fo.ok) return fo;
@@ -4593,9 +4747,32 @@ var decodeAction = (path, j) => {
4593
4747
  case "SetState": {
4594
4748
  const key = reqField(path, f, "key", "state key string", requireString);
4595
4749
  if (!key.ok) return key;
4596
- const valueJ = requireField(path, f, "value", "JsonValue value");
4597
- if (!valueJ.ok) return valueJ;
4598
- const value = decodeJVal(`${path}.value`, valueJ.value);
4750
+ const valueJ = tryField(f, "value");
4751
+ const fromJ = tryField(f, "valueFrom");
4752
+ if (valueJ !== void 0 && fromJ !== void 0) {
4753
+ return makeError(
4754
+ "WRONG_TYPE",
4755
+ `${path}.valueFrom`,
4756
+ "SetState carries both 'value' and 'valueFrom' \u2014 exactly one is allowed: 'value' is a literal JSON value written verbatim; 'valueFrom' derives the written value from a Binding at dispatch time; remove one"
4757
+ );
4758
+ }
4759
+ if (valueJ === void 0 && fromJ === void 0) {
4760
+ return makeError(
4761
+ "MISSING_FIELD",
4762
+ `${path}.value`,
4763
+ "missing required field 'value' \u2014 provide 'value' (a literal JSON value) or 'valueFrom' (a Binding evaluated at dispatch time)"
4764
+ );
4765
+ }
4766
+ if (fromJ !== void 0) {
4767
+ const from = decodeBinding(`${path}.valueFrom`, fromJ, decodeJVal, void 0);
4768
+ if (!from.ok) return from;
4769
+ return ok({
4770
+ kind: "SetState",
4771
+ key: key.value,
4772
+ valueFrom: from.value
4773
+ });
4774
+ }
4775
+ const value = decodeJVal(`${path}.value`, valueJ);
4599
4776
  return value.ok ? ok({ kind: "SetState", key: key.value, value: value.value }) : value;
4600
4777
  }
4601
4778
  case "AiTool": {
@@ -4804,14 +4981,18 @@ var decodeLinkSpec = (path, j) => {
4804
4981
  if (!rel.ok) return rel;
4805
4982
  const target = optField(path, f, "target", requireString);
4806
4983
  if (!target.ok) return target;
4984
+ const protection = optField(path, f, "protection", decodeLinkProtection);
4985
+ if (!protection.ok) return protection;
4807
4986
  return ok({
4808
4987
  href: href.value,
4809
4988
  label: label.value,
4810
4989
  download: download.value,
4811
4990
  ...rel.value !== void 0 ? { rel: rel.value } : {},
4812
- ...target.value !== void 0 ? { target: target.value } : {}
4991
+ ...target.value !== void 0 ? { target: target.value } : {},
4992
+ ...protection.value !== void 0 ? { protection: protection.value } : {}
4813
4993
  });
4814
4994
  };
4995
+ var decodeLinkProtection = (p, j) => bareEnum(p, j, ["email"], "LinkProtection");
4815
4996
  var decodeImageSpec = (path, j) => {
4816
4997
  const fo = requireObject(path, j);
4817
4998
  if (!fo.ok) return fo;
@@ -4918,6 +5099,28 @@ var decodeSkeletonSpec = (path, j) => {
4918
5099
  const rows = reqField(path, fo.value, "rows", "skeleton row count integer", requireInt);
4919
5100
  return rows.ok ? ok({ rows: rows.value }) : rows;
4920
5101
  };
5102
+ var decodeIconSize = (p, j) => bareEnum(p, j, ["Small", "Medium", "Large"], "IconSize");
5103
+ var decodeIconSpec = (path, j) => {
5104
+ const fo = requireObject(path, j);
5105
+ if (!fo.ok) return fo;
5106
+ const f = fo.value;
5107
+ const icon = reqField(path, f, "icon", "icon name string", requireString);
5108
+ if (!icon.ok) return icon;
5109
+ const sizeJ = tryField(f, "size");
5110
+ const size = sizeJ === void 0 ? ok("Medium") : decodeIconSize(`${path}.size`, sizeJ);
5111
+ if (!size.ok) return size;
5112
+ const toneJ = tryField(f, "tone");
5113
+ const tone = toneJ === void 0 ? ok("Default") : decodeTone(`${path}.tone`, toneJ);
5114
+ if (!tone.ok) return tone;
5115
+ const label = optField(path, f, "label", requireString);
5116
+ if (!label.ok) return label;
5117
+ return ok({
5118
+ icon: icon.value,
5119
+ size: size.value,
5120
+ tone: tone.value,
5121
+ ...label.value !== void 0 ? { label: label.value } : {}
5122
+ });
5123
+ };
4921
5124
  var decodeCalloutSpec = (path, j) => {
4922
5125
  const fo = requireObject(path, j);
4923
5126
  if (!fo.ok) return fo;
@@ -5008,6 +5211,10 @@ var decodeDrawStyle = (path, j) => {
5008
5211
  if (!fontFamily.ok) return fontFamily;
5009
5212
  const markId = optField(path, f, "markId", requireString);
5010
5213
  if (!markId.ok) return markId;
5214
+ const rotation = optField(path, f, "rotation", requireFloat);
5215
+ if (!rotation.ok) return rotation;
5216
+ const tip = optField(path, f, "tip", decodeTextSource);
5217
+ if (!tip.ok) return tip;
5011
5218
  return ok({
5012
5219
  ...fill.value !== void 0 ? { fill: fill.value } : {},
5013
5220
  ...stroke.value !== void 0 ? { stroke: stroke.value } : {},
@@ -5017,7 +5224,9 @@ var decodeDrawStyle = (path, j) => {
5017
5224
  ...fontSize.value !== void 0 ? { fontSize: fontSize.value } : {},
5018
5225
  ...emphasis.value !== void 0 ? { emphasis: emphasis.value } : {},
5019
5226
  ...fontFamily.value !== void 0 ? { fontFamily: fontFamily.value } : {},
5020
- ...markId.value !== void 0 ? { markId: markId.value } : {}
5227
+ ...markId.value !== void 0 ? { markId: markId.value } : {},
5228
+ ...rotation.value !== void 0 ? { rotation: rotation.value } : {},
5229
+ ...tip.value !== void 0 ? { tip: tip.value } : {}
5021
5230
  });
5022
5231
  };
5023
5232
  var decodeCurveCommand = (path, j) => {
@@ -5249,6 +5458,10 @@ var decodeDisplayKind = (path, j) => {
5249
5458
  const r = decodeSkeletonSpec(path, j);
5250
5459
  return r.ok ? ok({ kind: "Skeleton", spec: r.value }) : r;
5251
5460
  }
5461
+ case "Icon": {
5462
+ const r = decodeIconSpec(path, j);
5463
+ return r.ok ? ok({ kind: "Icon", spec: r.value }) : r;
5464
+ }
5252
5465
  case "LabelValueRow": {
5253
5466
  const r = decodeLabelValueRowSpec(path, j);
5254
5467
  return r.ok ? ok({ kind: "LabelValueRow", spec: r.value }) : r;
@@ -5732,7 +5945,7 @@ var decodeTonedPill = (path, f) => {
5732
5945
  };
5733
5946
  return ok(k);
5734
5947
  };
5735
- var decodeCellKindErased = (path, j) => {
5948
+ var decodeCellKindErased = (path, j, columnField) => {
5736
5949
  const fo = requireObject(path, j);
5737
5950
  if (!fo.ok) return fo;
5738
5951
  const f = fo.value;
@@ -5796,7 +6009,15 @@ var decodeCellKindErased = (path, j) => {
5796
6009
  case "TonedPill":
5797
6010
  return decodeTonedPill(path, f);
5798
6011
  case "Progress": {
5799
- const k = { kind: "Progress", fraction: () => 0 };
6012
+ const field2 = columnField;
6013
+ const k = {
6014
+ kind: "Progress",
6015
+ fraction: field2 === void 0 ? () => 0 : (row) => {
6016
+ const v = row !== null && typeof row === "object" ? row[field2] : void 0;
6017
+ const n = typeof v === "number" && Number.isFinite(v) ? v : 0;
6018
+ return Math.max(0, Math.min(1, n));
6019
+ }
6020
+ };
5800
6021
  return ok(k);
5801
6022
  }
5802
6023
  case "Custom": {
@@ -5814,13 +6035,78 @@ var decodeCellKindErased = (path, j) => {
5814
6035
  );
5815
6036
  }
5816
6037
  };
6038
+ var nearMiss = (path, found, canonical) => makeError(
6039
+ "WRONG_TYPE",
6040
+ `${path}.${found}`,
6041
+ `'${found}' is not part of the grid vocabulary \u2014 it would be ignored, not honoured`,
6042
+ canonical
6043
+ );
6044
+ var checkNearMisses = (path, f, candidates) => {
6045
+ for (const [name, canonical] of candidates) {
6046
+ if (tryField(f, name) !== void 0) return nearMiss(path, name, canonical);
6047
+ }
6048
+ return ok(void 0);
6049
+ };
6050
+ var COLUMN_NEAR_MISSES = [
6051
+ // Named by the census row itself. Deliberately NOT aliased to
6052
+ // `editable: false`: an inverting alias that guesses wrong makes a read-only
6053
+ // column editable.
6054
+ ["readOnly", "editable: false \u2014 the column flag NARROWS the grid's editable capability"]
6055
+ ];
6056
+ var GRID_NEAR_MISSES = [
6057
+ // The sharpest of them: a LITERAL page number is not expressible at all,
6058
+ // because the position lives in State so a control can move it. Ignoring it
6059
+ // is what produced the ×11 fake-affordance cluster.
6060
+ [
6061
+ "currentPage",
6062
+ 'pageStateKey \u2014 the page POSITION lives in State as {"page": N} so the pager can move it; a literal page number is not expressible'
6063
+ ],
6064
+ [
6065
+ "page",
6066
+ 'pageStateKey \u2014 the page POSITION lives in State as {"page": N} so the pager can move it; a literal page number is not expressible'
6067
+ ],
6068
+ [
6069
+ "pageIndex",
6070
+ 'pageStateKey \u2014 the page POSITION lives in State as {"page": N}, 1-based (not a zero-based index)'
6071
+ ],
6072
+ [
6073
+ "sortable",
6074
+ "sortStateKey on the grid + sortable on each COLUMN \u2014 grid-wide sortable is the staticRows spelling; a data-bound grid narrows per column"
6075
+ ],
6076
+ [
6077
+ "onEdit",
6078
+ "editStateKey \u2014 the edit DESTINATION is a State key on the grid; onEdit is a per-cell host closure and carries no destination across the wire"
6079
+ ],
6080
+ [
6081
+ "behaviour",
6082
+ "sibling fields on the grid (sortStateKey / pageStateKey / pageSize / editStateKey / defaultSort) \u2014 grid behaviour is not a nested record"
6083
+ ],
6084
+ [
6085
+ "behavior",
6086
+ "sibling fields on the grid (sortStateKey / pageStateKey / pageSize / editStateKey / defaultSort) \u2014 grid behaviour is not a nested record"
6087
+ ]
6088
+ ];
5817
6089
  var decodeColumnErased = (path, j) => {
5818
6090
  const fo = requireObject(path, j);
5819
6091
  if (!fo.ok) return fo;
5820
6092
  const f = fo.value;
5821
6093
  const format = optField(path, f, "format", decodeCellFormat);
5822
6094
  if (!format.ok) return format;
5823
- const kind = reqFieldAliased(path, f, "kind", ["type"], "CellKindErased", decodeCellKindErased);
6095
+ const fieldJ = tryField(f, "field");
6096
+ let field2;
6097
+ if (fieldJ !== void 0) {
6098
+ const fr = requireString(`${path}.field`, fieldJ);
6099
+ if (!fr.ok) return fr;
6100
+ field2 = fr.value;
6101
+ }
6102
+ const kind = reqFieldAliased(
6103
+ path,
6104
+ f,
6105
+ "kind",
6106
+ ["type"],
6107
+ "CellKindErased",
6108
+ (p, v) => decodeCellKindErased(p, v, field2)
6109
+ );
5824
6110
  if (!kind.ok) return kind;
5825
6111
  const label = reqFieldAliased(
5826
6112
  path,
@@ -5834,12 +6120,21 @@ var decodeColumnErased = (path, j) => {
5834
6120
  const width = optField(path, f, "width", decodeColumnWidth);
5835
6121
  if (!width.ok) return width;
5836
6122
  const hasValue = tryField(f, "value") !== void 0;
5837
- const fieldJ = tryField(f, "field");
5838
- let field2;
5839
- if (fieldJ !== void 0) {
5840
- const fr = requireString(`${path}.field`, fieldJ);
5841
- if (!fr.ok) return fr;
5842
- field2 = fr.value;
6123
+ const colNearMiss = checkNearMisses(path, f, COLUMN_NEAR_MISSES);
6124
+ if (!colNearMiss.ok) return colNearMiss;
6125
+ const colEditableJ = tryField(f, "editable");
6126
+ let colEditable;
6127
+ if (colEditableJ !== void 0) {
6128
+ const er = requireBool(`${path}.editable`, colEditableJ);
6129
+ if (!er.ok) return er;
6130
+ colEditable = er.value;
6131
+ }
6132
+ const sortableJ = tryField(f, "sortable");
6133
+ let sortable;
6134
+ if (sortableJ !== void 0) {
6135
+ const sr = requireBool(`${path}.sortable`, sortableJ);
6136
+ if (!sr.ok) return sr;
6137
+ sortable = sr.value;
5843
6138
  }
5844
6139
  return ok({
5845
6140
  format: format.value ?? { kind: "None" },
@@ -5847,9 +6142,27 @@ var decodeColumnErased = (path, j) => {
5847
6142
  label: label.value,
5848
6143
  width: width.value ?? { kind: "Auto" },
5849
6144
  ...hasValue ? { value: () => ({ kind: "Empty" }) } : {},
5850
- ...field2 !== void 0 ? { field: field2 } : {}
6145
+ ...field2 !== void 0 ? { field: field2 } : {},
6146
+ ...sortable !== void 0 ? { sortable } : {},
6147
+ ...colEditable !== void 0 ? { editable: colEditable } : {}
5851
6148
  });
5852
6149
  };
6150
+ var decodeSortDirection = (p, j) => bareEnum(p, j, ["asc", "desc"], "SortDirection");
6151
+ var decodeDefaultSort = (path, j) => {
6152
+ const fo = requireObject(path, j);
6153
+ if (!fo.ok) return fo;
6154
+ const f = fo.value;
6155
+ const columnJ = requireField(path, f, "column", "non-negative header index");
6156
+ if (!columnJ.ok) return columnJ;
6157
+ const cv = columnJ.value;
6158
+ if (cv.kind !== "JNumber" || cv.value < 0 || !Number.isInteger(cv.value))
6159
+ return wrongType(`${path}.column`, "JSON number (non-negative integer header index)");
6160
+ const directionJ = requireField(path, f, "direction", "asc | desc");
6161
+ if (!directionJ.ok) return directionJ;
6162
+ const direction = decodeSortDirection(`${path}.direction`, directionJ.value);
6163
+ if (!direction.ok) return direction;
6164
+ return ok({ column: cv.value, direction: direction.value });
6165
+ };
5853
6166
  var decodeStaticRows = (path, j) => {
5854
6167
  const fo = requireObject(path, j);
5855
6168
  if (!fo.ok) return fo;
@@ -5876,7 +6189,16 @@ var decodeStaticRows = (path, j) => {
5876
6189
  );
5877
6190
  });
5878
6191
  if (!rows.ok) return rows;
5879
- return ok({ headers: headers.value, rows: rows.value });
6192
+ const sortable = optField(path, f, "sortable", requireBool);
6193
+ if (!sortable.ok) return sortable;
6194
+ const defaultSort = optField(path, f, "defaultSort", decodeDefaultSort);
6195
+ if (!defaultSort.ok) return defaultSort;
6196
+ return ok({
6197
+ headers: headers.value,
6198
+ rows: rows.value,
6199
+ ...sortable.value !== void 0 ? { sortable: sortable.value } : {},
6200
+ ...defaultSort.value !== void 0 ? { defaultSort: defaultSort.value } : {}
6201
+ });
5880
6202
  };
5881
6203
  var decodeGridSpec = (path, j) => {
5882
6204
  const fo = requireObject(path, j);
@@ -5911,6 +6233,43 @@ var decodeGridSpec = (path, j) => {
5911
6233
  if (!rk.ok) return rk;
5912
6234
  rowKeyField = rk.value;
5913
6235
  }
6236
+ const sortStateKeyJ = tryField(f, "sortStateKey");
6237
+ let sortStateKey;
6238
+ if (sortStateKeyJ !== void 0) {
6239
+ const sk = requireString(`${path}.sortStateKey`, sortStateKeyJ);
6240
+ if (!sk.ok) return sk;
6241
+ sortStateKey = sk.value;
6242
+ }
6243
+ const pageSizeJ = tryField(f, "pageSize");
6244
+ let pageSize;
6245
+ if (pageSizeJ !== void 0) {
6246
+ if (pageSizeJ.kind !== "JNumber" || pageSizeJ.value < 1 || !Number.isInteger(pageSizeJ.value))
6247
+ return wrongType(`${path}.pageSize`, "JSON number (integer page size of 1 or more)");
6248
+ pageSize = pageSizeJ.value;
6249
+ }
6250
+ const defaultSortJ = tryField(f, "defaultSort");
6251
+ let defaultSort;
6252
+ if (defaultSortJ !== void 0) {
6253
+ const ds = decodeDefaultSort(`${path}.defaultSort`, defaultSortJ);
6254
+ if (!ds.ok) return ds;
6255
+ defaultSort = ds.value;
6256
+ }
6257
+ const gridNearMiss = checkNearMisses(path, f, GRID_NEAR_MISSES);
6258
+ if (!gridNearMiss.ok) return gridNearMiss;
6259
+ const editStateKeyJ = tryField(f, "editStateKey");
6260
+ let editStateKey;
6261
+ if (editStateKeyJ !== void 0) {
6262
+ const ek = requireString(`${path}.editStateKey`, editStateKeyJ);
6263
+ if (!ek.ok) return ek;
6264
+ editStateKey = ek.value;
6265
+ }
6266
+ const pageStateKeyJ = tryField(f, "pageStateKey");
6267
+ let pageStateKey;
6268
+ if (pageStateKeyJ !== void 0) {
6269
+ const pk = requireString(`${path}.pageStateKey`, pageStateKeyJ);
6270
+ if (!pk.ok) return pk;
6271
+ pageStateKey = pk.value;
6272
+ }
5914
6273
  const staticRowsJ = tryField(f, "staticRows");
5915
6274
  let staticRows;
5916
6275
  if (staticRowsJ !== void 0) {
@@ -5925,6 +6284,11 @@ var decodeGridSpec = (path, j) => {
5925
6284
  ...hasRowClick ? { onRowClick: () => placeholderAction } : {},
5926
6285
  ...hasRowKey ? { rowKey: () => CLOSURE2 } : {},
5927
6286
  ...rowKeyField !== void 0 ? { rowKeyField } : {},
6287
+ ...sortStateKey !== void 0 ? { sortStateKey } : {},
6288
+ ...pageSize !== void 0 ? { pageSize } : {},
6289
+ ...pageStateKey !== void 0 ? { pageStateKey } : {},
6290
+ ...defaultSort !== void 0 ? { defaultSort } : {},
6291
+ ...editStateKey !== void 0 ? { editStateKey } : {},
5928
6292
  ...staticRows !== void 0 ? { staticRows } : {}
5929
6293
  });
5930
6294
  };
@@ -5956,6 +6320,20 @@ var decodeChartSpec = (path, j) => {
5956
6320
  if (!yFields.ok) return yFields;
5957
6321
  const title = optField(path, f, "title", decodeTextSource);
5958
6322
  if (!title.ok) return title;
6323
+ const valueFormat = optField(path, f, "valueFormat", decodeFormat);
6324
+ if (!valueFormat.ok) return valueFormat;
6325
+ const xTitle = optField(path, f, "xTitle", decodeTextSource);
6326
+ if (!xTitle.ok) return xTitle;
6327
+ const yTitle = optField(path, f, "yTitle", decodeTextSource);
6328
+ if (!yTitle.ok) return yTitle;
6329
+ const subtitle = optField(path, f, "subtitle", decodeTextSource);
6330
+ if (!subtitle.ok) return subtitle;
6331
+ const legendPosition = optField(path, f, "legendPosition", decodeChartLegendPosition);
6332
+ if (!legendPosition.ok) return legendPosition;
6333
+ const dataLabels = optField(path, f, "dataLabels", decodeChartDataLabels);
6334
+ if (!dataLabels.ok) return dataLabels;
6335
+ const xScale = optField(path, f, "xScale", decodeChartXScale);
6336
+ if (!xScale.ok) return xScale;
5959
6337
  const hasPointClick = tryField(f, "onPointClick") !== void 0;
5960
6338
  const stacked = optField(path, f, "stacked", requireBool);
5961
6339
  if (!stacked.ok) return stacked;
@@ -5966,6 +6344,13 @@ var decodeChartSpec = (path, j) => {
5966
6344
  yFields: yFields.value,
5967
6345
  stacked: stacked.value ?? false,
5968
6346
  ...title.value !== void 0 ? { title: title.value } : {},
6347
+ ...valueFormat.value !== void 0 ? { valueFormat: valueFormat.value } : {},
6348
+ ...xTitle.value !== void 0 ? { xTitle: xTitle.value } : {},
6349
+ ...yTitle.value !== void 0 ? { yTitle: yTitle.value } : {},
6350
+ ...subtitle.value !== void 0 ? { subtitle: subtitle.value } : {},
6351
+ ...legendPosition.value !== void 0 ? { legendPosition: legendPosition.value } : {},
6352
+ ...dataLabels.value !== void 0 ? { dataLabels: dataLabels.value } : {},
6353
+ ...xScale.value !== void 0 ? { xScale: xScale.value } : {},
5969
6354
  ...hasPointClick ? { onPointClick: () => placeholderAction } : {}
5970
6355
  });
5971
6356
  };
@@ -6532,6 +6917,7 @@ var decodeNodeKind = (path, j) => {
6532
6917
  case "Callout":
6533
6918
  case "Progress":
6534
6919
  case "Skeleton":
6920
+ case "Icon":
6535
6921
  case "LabelValueRow":
6536
6922
  case "Fact":
6537
6923
  case "Link":
@@ -7042,7 +7428,11 @@ var coerce = {
7042
7428
  emphasisFlag: (v) => viaAst(v, decodeEmphasisFlag),
7043
7429
  headingVariant: (v) => viaAst(v, decodeHeadingVariant),
7044
7430
  badgeVariant: (v) => viaAst(v, decodeBadgeVariant),
7045
- iconSource: (v) => viaAst(v, decodeIconSource)
7431
+ iconSource: (v) => viaAst(v, decodeIconSource),
7432
+ /** `Icon.Size : IconSize` (Phase 821) — the UpdateProp twin of `decodeIconSize`,
7433
+ * added with the standalone Icon display kind. */
7434
+ iconSize: (v) => viaAst(v, decodeIconSize),
7435
+ stringOption: (v) => viaAst(v, parseStaticStringOpt)
7046
7436
  };
7047
7437
  var invalidJson = (parseMessage) => makeError(
7048
7438
  "INVALID_JSON",
@@ -7280,6 +7670,37 @@ var updateField = (field2, value, kind) => {
7280
7670
  }
7281
7671
  case "Skeleton":
7282
7672
  return field2 === "Rows" ? patch(coerce.int(value), (x) => disp({ kind: "Skeleton", spec: { rows: x } })) : { tag: "unknownField" };
7673
+ case "Icon": {
7674
+ const s = d.spec;
7675
+ switch (field2) {
7676
+ case "Icon":
7677
+ return patch(
7678
+ coerce.string(value),
7679
+ (x) => disp({ kind: "Icon", spec: { ...s, icon: x } })
7680
+ );
7681
+ case "Size":
7682
+ return patch(
7683
+ coerce.iconSize(value),
7684
+ (x) => disp({ kind: "Icon", spec: { ...s, size: x } })
7685
+ );
7686
+ case "Tone":
7687
+ return patch(
7688
+ coerce.tone(value),
7689
+ (x) => disp({ kind: "Icon", spec: { ...s, tone: x } })
7690
+ );
7691
+ case "Label": {
7692
+ return patch(coerce.stringOption(value), (x) => {
7693
+ const { label: _label, ...rest } = s;
7694
+ return disp({
7695
+ kind: "Icon",
7696
+ spec: { ...rest, ...x !== void 0 ? { label: x } : {} }
7697
+ });
7698
+ });
7699
+ }
7700
+ default:
7701
+ return { tag: "unknownField" };
7702
+ }
7703
+ }
7283
7704
  case "Callout": {
7284
7705
  const s = d.spec;
7285
7706
  switch (field2) {
@@ -8087,6 +8508,168 @@ var apply = (tree, op) => {
8087
8508
  return { ok: true, value: { newTree: r.value, emittedTelemetry: telem } };
8088
8509
  };
8089
8510
 
8511
+ // src/placement.ts
8512
+ var derivedFreshIds = (oldId, taken) => {
8513
+ for (let n = 1; ; n += 1) {
8514
+ const candidate = n === 1 ? `${oldId}-copy` : `${oldId}-copy-${n}`;
8515
+ if (!taken(candidate)) return candidate;
8516
+ }
8517
+ };
8518
+ var sequentialFreshIds = (prefix) => {
8519
+ let counter = 0;
8520
+ return (_oldId, taken) => {
8521
+ for (; ; ) {
8522
+ counter += 1;
8523
+ const candidate = `${prefix}-${counter}`;
8524
+ if (!taken(candidate)) return candidate;
8525
+ }
8526
+ };
8527
+ };
8528
+ var ok3 = (value) => ({ ok: true, value });
8529
+ var err = (error) => ({ ok: false, error });
8530
+ var idOf2 = (n) => n.id;
8531
+ var sameOrder = (a, b) => a.length === b.length && a.every((id, i) => id === b[i]);
8532
+ var containerChildren = (root, parentId) => {
8533
+ const parent = findNode(parentId, root);
8534
+ if (parent === void 0) return err({ kind: "ParentNotFound", parentId });
8535
+ const children = layoutChildren(parent);
8536
+ if (children === void 0) return err({ kind: "ChildlessKind", parentId });
8537
+ return ok3(children.map(idOf2));
8538
+ };
8539
+ var reposition = (order, moved, placement) => {
8540
+ const rest = order.filter((id) => id !== moved);
8541
+ const anchored = (anchor, offset) => {
8542
+ const i = rest.findIndex((id) => id === anchor);
8543
+ if (i < 0) return err({ kind: "UnknownAnchor", anchor });
8544
+ const at = i + offset;
8545
+ return ok3([...rest.slice(0, at), moved, ...rest.slice(at)]);
8546
+ };
8547
+ switch (placement.kind) {
8548
+ case "Last":
8549
+ return ok3([...rest, moved]);
8550
+ case "First":
8551
+ return ok3([moved, ...rest]);
8552
+ case "Before":
8553
+ return anchored(placement.anchor, 0);
8554
+ case "After":
8555
+ return anchored(placement.anchor, 1);
8556
+ }
8557
+ };
8558
+ var structurallyPresent = (nodeId, root) => idOf2(root) === nodeId || findLayoutParent(nodeId, root) !== void 0;
8559
+ var firstSharedId = (root, incoming) => {
8560
+ const existing = new Set(allNodeIds(root));
8561
+ return allNodeIds(incoming).find((id) => existing.has(id));
8562
+ };
8563
+ var canPlace = (root, moved, target) => {
8564
+ const r = root;
8565
+ if (!structurallyPresent(moved, r)) return err({ kind: "NodeNotFound", nodeId: moved });
8566
+ if (target.parentId === moved) return err({ kind: "MoveIntoSelf", nodeId: moved });
8567
+ if (isAncestor(moved, target.parentId, r))
8568
+ return err({ kind: "MoveIntoDescendant", nodeId: moved, parentId: target.parentId });
8569
+ const siblings = containerChildren(r, target.parentId);
8570
+ if (!siblings.ok) return siblings;
8571
+ const membership = [...siblings.value.filter((id) => id !== moved), moved];
8572
+ const placed = reposition(membership, moved, target.placement);
8573
+ return placed.ok ? ok3(void 0) : placed;
8574
+ };
8575
+ var placeOp = (root, child, target) => {
8576
+ const r = root;
8577
+ const siblings = containerChildren(r, target.parentId);
8578
+ if (!siblings.ok) return siblings;
8579
+ const dup = firstSharedId(r, child);
8580
+ if (dup !== void 0) return err({ kind: "DuplicateId", nodeId: dup });
8581
+ const childId = idOf2(child);
8582
+ const appended = [...siblings.value, childId];
8583
+ const wanted = reposition(appended, childId, target.placement);
8584
+ if (!wanted.ok) return wanted;
8585
+ const insert = { kind: "InsertChild", parentId: target.parentId, child };
8586
+ return ok3(
8587
+ sameOrder(wanted.value, appended) ? insert : {
8588
+ kind: "Batch",
8589
+ ops: [
8590
+ insert,
8591
+ { kind: "ReorderChildren", parentId: target.parentId, newOrder: wanted.value }
8592
+ ]
8593
+ }
8594
+ );
8595
+ };
8596
+ var moveOp = (root, moved, target) => {
8597
+ const legal = canPlace(root, moved, target);
8598
+ if (!legal.ok) return legal;
8599
+ const siblings = containerChildren(root, target.parentId);
8600
+ if (!siblings.ok) return siblings;
8601
+ const appended = [...siblings.value.filter((id) => id !== moved), moved];
8602
+ const wanted = reposition(appended, moved, target.placement);
8603
+ if (!wanted.ok) return wanted;
8604
+ const move = { kind: "MoveNode", target: moved, newParentId: target.parentId };
8605
+ return ok3(
8606
+ sameOrder(wanted.value, appended) ? move : {
8607
+ kind: "Batch",
8608
+ ops: [
8609
+ move,
8610
+ { kind: "ReorderChildren", parentId: target.parentId, newOrder: wanted.value }
8611
+ ]
8612
+ }
8613
+ );
8614
+ };
8615
+ var nudgeOp = (root, nodeId, delta) => {
8616
+ const r = root;
8617
+ if (idOf2(r) === nodeId) return err({ kind: "CannotNudgeRoot", nodeId });
8618
+ const parent = findLayoutParent(nodeId, r);
8619
+ if (parent === void 0) return err({ kind: "NodeNotFound", nodeId });
8620
+ const ids = (layoutChildren(parent) ?? []).map(idOf2);
8621
+ const index = ids.findIndex((id) => id === nodeId);
8622
+ const swapWith = index + delta;
8623
+ if (swapWith < 0 || swapWith >= ids.length)
8624
+ return err({ kind: "NudgeOutOfRange", nodeId, delta });
8625
+ const reordered = ids.map(
8626
+ (id, i) => i === index ? ids[swapWith] : i === swapWith ? ids[index] : id
8627
+ );
8628
+ return ok3({ kind: "ReorderChildren", parentId: idOf2(parent), newOrder: reordered });
8629
+ };
8630
+ var mapImmediate = (n, f) => {
8631
+ let cur = n;
8632
+ const count = childSlots(n).length;
8633
+ for (let i = 0; i < count; i += 1) {
8634
+ const slot = childSlots(cur)[i];
8635
+ const mapped = f(slot.child);
8636
+ if (mapped !== slot.child) cur = slot.rebuild(mapped);
8637
+ }
8638
+ return cur;
8639
+ };
8640
+ var remapForInsert = (freshIds, targetRoot, incoming) => {
8641
+ const existing = new Set(allNodeIds(targetRoot));
8642
+ const taken = /* @__PURE__ */ new Set([...existing, ...allNodeIds(incoming)]);
8643
+ const rename = /* @__PURE__ */ new Map();
8644
+ for (const oldId of allNodeIds(incoming)) {
8645
+ if (existing.has(oldId)) {
8646
+ const fresh = freshIds(oldId, (candidate) => taken.has(candidate));
8647
+ taken.add(fresh);
8648
+ rename.set(oldId, fresh);
8649
+ }
8650
+ }
8651
+ if (rename.size === 0) return incoming;
8652
+ const rewrite = (node2) => {
8653
+ const withChildren = mapImmediate(node2, rewrite);
8654
+ const fresh = rename.get(withChildren.id);
8655
+ return fresh === void 0 ? withChildren : { ...withChildren, id: fresh };
8656
+ };
8657
+ return rewrite(incoming);
8658
+ };
8659
+ var duplicateOpWith = (freshIds, root, source, target) => {
8660
+ const r = root;
8661
+ const sub = findNode(source, r);
8662
+ if (sub === void 0) return err({ kind: "NodeNotFound", nodeId: source });
8663
+ return placeOp(root, remapForInsert(freshIds, r, sub), target);
8664
+ };
8665
+ var duplicateOp = (root, source, target) => duplicateOpWith(derivedFreshIds, root, source, target);
8666
+ var pasteOpWith = (freshIds, targetRoot, incoming, target) => placeOp(
8667
+ targetRoot,
8668
+ remapForInsert(freshIds, targetRoot, incoming),
8669
+ target
8670
+ );
8671
+ var pasteOp = (targetRoot, incoming, target) => pasteOpWith(derivedFreshIds, targetRoot, incoming, target);
8672
+
8090
8673
  // src/dag.ts
8091
8674
  var str2 = (s) => {
8092
8675
  let out = '"';
@@ -9178,6 +9761,6 @@ var validateAnswerDocument = (json) => {
9178
9761
  return validateAnswerAt("$.answer", contract.value, answer.value);
9179
9762
  };
9180
9763
 
9181
- export { ELICITATION_KEY, ELICITATION_VERSION, PAYLOAD_KEY, PROFILE_KEY, REQUIRED_PROFILE_KEY, apply, cellString, coerce, coreV1, decodeDagRecord, decodeElicitation, decodeElicitationOutcome, decodeEnvelope, decodeEnvelopeAst, decodeNode, decodeNodeTolerant, decodeOp, decodeTolerant, encodeCell, encodeColExpr, encodeDagRecord, encodeDataSource, encodeElicitation, encodeElicitationOutcome, encodeEnvelope2 as encodeEnvelope, encodeNode, encodeOp, encodePipeline, evalErrorString, evalPipeline, evalPipelineInEnv, evalPipelineWith, evalPipelineWithInEnv, evalSource, field as jsonField, merge3Way, negotiate, negotiateEnvelope, noResolve, parse, pipelineParams, reencodeNode, renderAstCanonical, renderProfile, stepParams, tryParseProfile, validateAnswer, validateAnswerAt, validateAnswerDocument };
9764
+ export { ELICITATION_KEY, ELICITATION_VERSION, PAYLOAD_KEY, PROFILE_KEY, REQUIRED_PROFILE_KEY, apply, canPlace, cellString, coerce, coreV1, decodeDagRecord, decodeElicitation, decodeElicitationOutcome, decodeEnvelope, decodeEnvelopeAst, decodeNode, decodeNodeTolerant, decodeOp, decodeTolerant, derivedFreshIds, duplicateOp, duplicateOpWith, encodeCell, encodeColExpr, encodeDagRecord, encodeDataSource, encodeElicitation, encodeElicitationOutcome, encodeEnvelope2 as encodeEnvelope, encodeNode, encodeOp, encodePipeline, evalErrorString, evalPipeline, evalPipelineInEnv, evalPipelineWith, evalPipelineWithInEnv, evalSource, field as jsonField, liveValueToTable, merge3Way, moveOp, negotiate, negotiateEnvelope, noResolve, nudgeOp, parse, pasteOp, pasteOpWith, pipelineParams, placeOp, reencodeNode, renderAstCanonical, renderProfile, sequentialFreshIds, stepParams, tryParseProfile, validateAnswer, validateAnswerAt, validateAnswerDocument };
9182
9765
  //# sourceMappingURL=index.js.map
9183
9766
  //# sourceMappingURL=index.js.map